Docker 环境下 MySQL 一主一从同步实战
前言
在实际开发与生产场景中,MySQL 单节点往往无法满足高可用、高并发以及数据备份的需求。主从复制作为 MySQL 最经典的高可用方案,能够实现读写分离、故障转移与数据冗余备份。
本文将基于 Docker 容器化环境,使用 MySQL 8.3.0 版本快速搭建一主一从架构,全程通过自动化 Shell 脚本实现部署,无需手动修改复杂配置文件,可复现、易维护,非常适合学习与测试环境使用。
一、环境说明
- 操作系统:Windows + WSL2
- 容器引擎:Docker
- MySQL 版本:8.3.0
- 主库端口:3307
- 从库端口:3308
- root 密码:123456
- 复制账号:repl / 123456
二、主从复制原理简述
主库(Master)
- 开启二进制日志
binlog,所有数据变更都会记录到 binlog 中。 - 为 IO 线程提供 binlog 读取权限。
- 开启二进制日志
从库(Slave)
- IO 线程:连接主库,请求并接收 binlog,写入中继日志
relay log。 - SQL 线程:读取中继日志,重放 SQL 语句,实现数据同步。
- IO 线程:连接主库,请求并接收 binlog,写入中继日志
三、一键部署脚本
为了简化部署流程,避免手动配置出错,编写自动化 Shell 脚本mysql_ms_deploy.sh。
bash
运行
#!/bin/bash # ====================== MySQL 8.3.0 主从一键脚本 ====================== # 主库:3307 从库:3308 密码:123456 # ====================================================================== echo "=============================================" echo " MySQL 8.3.0 Master-Slave Deploy" echo " Master: 3307 | Slave: 3308" echo " Password: 123456" echo "=============================================" # 1. 清理旧容器 echo -e "\n[1/6] 清理旧容器..." docker rm -f mysql-master mysql-slave >/dev/null 2>&1 # 2. 启动主库 echo -e "\n[2/6] 启动主库(3307)..." docker run -d --name mysql-master \ -p 3307:3306 \ -e MYSQL_ROOT_PASSWORD=123456 \ mysql:8.3.0 \ --server-id=1 \ --log-bin=mysql-bin \ --binlog-format=ROW # 3. 启动从库 echo -e "\n[3/6] 启动从库(3308)..." docker run -d --name mysql-slave \ -p 3308:3306 \ -e MYSQL_ROOT_PASSWORD=123456 \ mysql:8.3.0 \ --server-id=2 \ --relay-log=relay-bin # 4. 等待MySQL启动 echo -e "\n[4/6] 等待MySQL启动 15秒..." sleep 15 # 5. 创建同步账号 echo -e "\n[5/6] 创建同步账号 repl..." docker exec mysql-master mysql -uroot -p123456 -e " CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; FLUSH PRIVILEGES; " 2>/dev/null # 6. 获取主库信息并配置从库 echo -e "\n[6/6] 配置主从同步..." file=$(docker exec mysql-master mysql -uroot -p123456 -N -e "SHOW MASTER STATUS;" 2>/dev/null | awk '{print $1}') pos=$(docker exec mysql-master mysql -uroot -p123456 -N -e "SHOW MASTER STATUS;" 2>/dev/null | awk '{print $2}') master_ip=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mysql-master) docker exec mysql-slave mysql -uroot -p123456 -e " STOP SLAVE; RESET SLAVE ALL; CHANGE MASTER TO MASTER_HOST='$master_ip', MASTER_USER='repl', MASTER_PASSWORD='123456', MASTER_LOG_FILE='$file', MASTER_LOG_POS=$pos; START SLAVE; " 2>/dev/null # 输出结果 echo -e "\n=============================================" echo "✅ 部署完成!" echo "主库:localhost:3307 root / 123456" echo "从库:localhost:3308 root / 123456" echo -e "=============================================\n" echo "🔍 从库同步状态:" docker exec mysql-slave mysql -uroot -p123456 -e "SHOW SLAVE STATUS\G" 2>/dev/null | grep "Slave_IO_Running\|Slave_SQL_Running" echo -e "\n🎉 部署成功!"四、脚本执行步骤
- 赋予脚本执行权限
bash
运行
chmod +x mysql_ms_deploy.sh- 运行脚本
bash
运行
./mysql_ms_deploy.sh- 等待执行完成,出现以下结果表示主从同步正常:
plaintext
Slave_IO_Running: Yes Slave_SQL_Running: Yes五、主从同步测试
- 主库写入数据
bash
运行
docker exec mysql-master mysql -uroot -p123456 -e "CREATE DATABASE testdb; USE testdb; CREATE TABLE user(id INT); INSERT INTO user VALUES(1);"- 从库查询验证
bash
运行
docker exec mysql-slave mysql -uroot -p123456 -e "SELECT * FROM testdb.user;"若能正常查询到数据,说明主从复制搭建成功。
六、常见问题与排错
Slave_IO_Running: Connecting
- 主从网络不通
- 复制账号密码错误
- 主库 binlog 未正常开启
Slave_SQL_Running: No
- 主从数据不一致
- 从库执行 SQL 报错
- 跳过事务可临时修复:
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
Docker 镜像拉取失败
- 更换镜像加速源
- 执行
docker system prune -a清理缓存
项目配置演示:
七、总结
通过 Docker 可以快速、干净地部署 MySQL 主从架构,避免了传统安装方式的环境污染与复杂配置。本文提供的一键脚本自动完成:
- 容器创建与端口映射
- server-id、binlog、relay-log 配置
- 复制账号创建
- 从库自动指向主库
- 状态自动检查
整套方案可直接用于学习、测试与演示,也可在此基础上扩展为 MGR、半同步复制、读写分离等更高级架构。