把运行在Docker中的MySQL数据库从一个环境迁移到另一个环境,是运维人员和开发者的高频需求。我经历过数十次不同规模的MySQL容器迁移,从单机测试环境到跨机房生产集群,总结出一套稳定可靠的迁移方案。
迁移的本质是保证数据一致性和服务连续性。与物理机或虚拟机迁移不同,容器迁移需要同时考虑镜像层、数据卷和网络配置三大要素。MySQL作为有状态服务,其数据目录必须通过Volume持久化,这是迁移过程中最需要谨慎处理的环节。
执行迁移前必须确认以下信息:
mysql --version)docker inspect查看Mounts字段)SELECT table_schema "Database", ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) "Size (MB)" FROM information_schema.TABLES GROUP BY table_schema;)根据业务需求选择合适方案:
| 方案类型 | 适用场景 | 停机时间 | 复杂度 |
|---|---|---|---|
| 导出导入 | 小数据量(<10GB) | 分钟级 | 低 |
| 物理文件迁移 | 大数据量(>10GB) | 秒级 | 高 |
关键提示:无论选择哪种方案,迁移前必须用
FLUSH TABLES WITH READ LOCK锁定数据库,确保数据一致性。
bash复制# 在源容器执行导出
docker exec -it mysql_container mysqldump -u root -p --all-databases --single-transaction > full_backup.sql
# 在新环境启动临时容器
docker run -d --name temp_mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 mysql:5.7
# 导入数据
docker exec -i temp_mysql mysql -u root -p123456 < full_backup.sql
# 验证数据完整性
docker exec -it temp_mysql mysql -u root -p123456 -e "SHOW DATABASES;"
bash复制# 停止源容器
docker stop mysql_container
# 备份数据卷(假设卷名为mysql_data)
docker run --rm --volumes-from mysql_container -v $(pwd):/backup busybox tar cvf /backup/mysql_backup.tar /var/lib/mysql
# 在新主机恢复
docker run --rm -v mysql_data:/target -v $(pwd):/backup busybox tar xvf /backup/mysql_backup.tar
# 启动新容器
docker run -d --name new_mysql -v mysql_data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 mysql:5.7
完成迁移后必须执行以下检查:
基础验证:
SELECT COUNT(*) FROM information_schema.TABLES)高级验证:
sql复制# 校验字符集
SHOW VARIABLES LIKE 'character_set%';
# 校验用户权限
SELECT user, host FROM mysql.user;
性能验证:
SHOW VARIABLES LIKE 'slow_query_log%')遇到中文乱码时,在my.cnf增加配置:
code复制[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
对于超过50GB的单表:
mydumper替代mysqldump(并行导出)--skip-lock-tables参数避免长时间锁表split命令分割SQL文件)迁移过程中网络故障时:
rsync替代scp实现断点续传md5sum backup.sql)以下脚本实现一键迁移验证:
bash复制#!/bin/bash
# 迁移验证脚本
SOURCE_CONTAINER=$1
TARGET_CONTAINER=$2
# 导出源数据库结构
docker exec $SOURCE_CONTAINER mysqldump -u root -p$PASS --no-data > schema.sql
# 在新容器导入结构
docker exec -i $TARGET_CONTAINER mysql -u root -p$PASS < schema.sql
# 对比表结构
diff <(docker exec $SOURCE_CONTAINER mysql -u root -p$PASS -N -e "SHOW TABLES;") \
<(docker exec $TARGET_CONTAINER mysql -u root -p$PASS -N -e "SHOW TABLES;")
建议将上述流程封装到CI/CD流水线中,结合Kubernetes的Init Container实现无人值守迁移。对于生产环境,还需要考虑binlog位置同步等高级特性,这需要根据具体MySQL复制架构进行调整。