在实际生产环境中,MySQL容器迁移是个高频需求。我经历过数十次不同规模的数据库容器迁移,从开发测试环境到生产集群,从单机部署到跨服务器迁移。每次迁移背后都有明确的技术诉求:可能是硬件升级需要更换宿主机,或是容器编排架构调整,也可能是单纯的备份容灾需求。
MySQL作为有状态服务,迁移过程远比无状态容器复杂。数据一致性、连接中断时间、权限配置恢复都是必须谨慎处理的要点。上周我刚帮一个电商团队完成高峰期MySQL容器迁移,整个过程零数据丢失,服务中断控制在15秒内。下面就把这套经过实战检验的方法论拆解给你。
执行迁移前,先用这个检查表确认基础环境:
bash复制# 检查原容器配置
docker inspect mysql_container | grep -E 'Mounts|Ports|Env'
# 验证数据卷实际路径
df -h $(docker volume inspect mysql_data | grep Mountpoint | cut -d'"' -f4)
# 记录关键参数
docker exec mysql_container mysql --version
docker exec mysql_container env | grep MYSQL_
重要提示:务必记录原容器的以下信息:
- 数据卷挂载路径(特别是自定义路径的情况)
- 暴露的端口号(包括容器内外端口映射)
- 环境变量(尤其是MYSQL_ROOT_PASSWORD等敏感配置)
- 自定义配置文件路径(如my.cnf)
我强烈推荐采用双保险策略:
物理备份:直接复制整个数据目录
bash复制# 创建临时快照(需要停止容器)
docker stop mysql_container
cp -rp /var/lib/docker/volumes/mysql_data/_data /backup/mysql/full_$(date +%Y%m%d)
docker start mysql_container
逻辑备份:用mysqldump导出SQL
bash复制docker exec mysql_container \
mysqldump -uroot -p$MYSQL_ROOT_PASSWORD --all-databases --single-transaction > /backup/mysql/full_$(date +%Y%m%d).sql
实战经验:物理备份恢复更快但可能有版本兼容问题,逻辑备份更通用但恢复耗时较长。重要迁移前两种备份都要做。
在新宿主机上预配环境:
bash复制# 创建数据目录(保持与原环境相同路径)
mkdir -p /var/lib/docker/volumes/mysql_data/_data
# 拉取相同版本的MySQL镜像
docker pull mysql:5.7.34 # 版本号需与原容器一致
# 准备配置文件(如有自定义配置)
vim /etc/mysql/my.cnf
根据网络条件选择合适方案:
| 方案 | 适用场景 | 命令示例 |
|---|---|---|
| SCP直传 | 同机房迁移 | scp -r /backup/mysql/full_20230801 root@new_host:/var/lib/docker/volumes/mysql_data/_data |
| Rsync增量 | 大容量数据 | rsync -avz --progress /backup/mysql/full_20230801/ new_host:/var/lib/docker/volumes/mysql_data/_data |
| 云存储中转 | 跨地域迁移 | 先上传到OSS/S3,再从目标机下载 |
使用与原容器一致的启动命令:
bash复制docker run -d \
--name mysql_container \
-v /var/lib/docker/volumes/mysql_data/_data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=your_secure_password \
-p 3306:3306 \
--restart unless-stopped \
mysql:5.7.34 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci
关键参数说明:
-v 挂载点必须与原路径一致-e 环境变量特别是密码要正确--restart 建议保持与原策略相同bash复制# 验证表数量
docker exec mysql_container mysql -uroot -p -e "SELECT COUNT(*) FROM information_schema.tables"
# 抽样检查关键表数据
docker exec mysql_container mysql -uroot -p -e "SELECT COUNT(*) FROM orders.orders WHERE created_at > '2023-07-01'"
# 校验用户权限
docker exec mysql_container mysql -uroot -p -e "SELECT user,host FROM mysql.user"
推荐采用分阶段切换:
避坑指南:切换前务必在业务低峰期进行,并提前通知相关团队。我曾遇到因未通知BI团队导致报表任务失败的情况。
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| ERROR 2002 | 端口冲突或未启动 | 检查端口占用 `netstat -tulnp |
| Table doesn't exist | 数据目录权限问题 | chown -R 999:999 /var/lib/mysql |
| Access denied | 密码未正确迁移 | 检查环境变量或使用 --skip-grant-tables 临时启动 |
迁移后常见性能问题处理:
bash复制# 检查慢查询
docker exec mysql_container mysql -uroot -p -e "SHOW VARIABLES LIKE 'slow_query%'"
# 临时增加缓冲池(根据新机器内存调整)
docker update mysql_container --memory=4g --memory-swap=4g
docker exec mysql_container mysql -uroot -p -e "SET GLOBAL innodb_buffer_pool_size=2147483648;"
对于复制集群的迁移要特别注意:
STOP SLAVE;SHOW MASTER STATUS;sql复制CHANGE MASTER TO
MASTER_HOST='new_master_ip',
MASTER_USER='repl_user',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000002',
MASTER_LOG_POS=107;
MySQL大版本升级迁移步骤:
mysql_upgrademysqldump --compatible 导出--upgrade=FORCE 参数对于需要频繁迁移的场景,可以封装成脚本:
bash复制#!/bin/bash
# 迁移MySQL容器脚本(需根据实际情况修改参数)
OLD_HOST="192.168.1.100"
NEW_HOST="192.168.1.101"
MYSQL_PASS="Secure@123"
BACKUP_DIR="/backup/mysql"
# 在原主机执行备份
ssh root@$OLD_HOST <<EOF
docker exec mysql mysqldump -uroot -p$MYSQL_PASS --all-databases --single-transaction > $BACKUP_DIR/migrate.sql
docker stop mysql
tar czf $BACKUP_DIR/mysql_data.tar.gz /var/lib/docker/volumes/mysql_data/_data
docker start mysql
EOF
# 传输到新主机
scp root@$OLD_HOST:$BACKUP_DIR/migrate.sql $BACKUP_DIR/
scp root@$OLD_HOST:$BACKUP_DIR/mysql_data.tar.gz $BACKUP_DIR/
# 在新主机恢复
docker run -d --name mysql_temp -e MYSQL_ROOT_PASSWORD=$MYSQL_PASS mysql:5.7
sleep 30 # 等待容器初始化
docker exec -i mysql_temp mysql -uroot -p$MYSQL_PASS < $BACKUP_DIR/migrate.sql
docker stop mysql_temp && docker rm mysql_temp
# 正式启动容器
tar xzf $BACKUP_DIR/mysql_data.tar.gz -C /var/lib/docker/volumes/mysql_data/_data
docker run -d --name mysql -v /var/lib/docker/volumes/mysql_data/_data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=$MYSQL_PASS -p 3306:3306 mysql:5.7
这个脚本经过我们团队多次优化,关键改进点包括:
最后特别提醒:无论迁移方案多么完善,都要在测试环境充分验证。我习惯在迁移前用sysbench生成测试数据,迁移后对比md5校验和确保比特级一致。对于金融类业务,还会用pt-table-checksum做更严格的数据校验。