本文基于 Windows + Docker Desktop + MySQL 8
不是"命令堆砌教程",而是一篇 真实踩坑后总结的可落地实践文档
一、背景说明
在学习分布式系统和数据库高可用时,MySQL 主从复制是绕不开的基础能力。
很多教程看起来步骤简单,但实际操作中极容易遇到问题,例如:
- Slave 一直
Connecting - 一写数据
Replica_SQL_Running就变成No Last_Errno: 1049 Unknown database- 看起来都配对了,但就是不同步
本文记录了我使用 Docker 搭建 MySQL 主从复制的完整过程 + 排坑经验。
二、整体架构
架构目标
- 使用 Docker 启动两个 MySQL 8 容器
- 一个作为 Master
- 一个作为 Slave
- Master 写入数据,Slave 自动同步
架构示意
+------------------+ binlog +------------------+
| MySQL Master | ----------------> | MySQL Slave |
| server-id=1 | | server-id=2 |
| 写 binlog | | 回放 binlog |
+------------------+ +------------------+
三、环境准备
- Windows 10 / 11
- Docker Desktop(WSL2 后端)
- PowerShell
- MySQL 镜像:
mysql:8.0
确认 Docker 正常:
powershell
docker ps
四、创建 Docker 网络(非常关键)
❗ 主从容器必须在同一个 Docker 网络中
powershell
docker network create mysql-net
验证:
powershell
docker network ls
五、启动 MySQL Master
1️⃣ 启动容器
powershell
docker run -d `
--name master `
--network mysql-net `
-e MYSQL_ROOT_PASSWORD=root `
-p 3306:3306 `
mysql:8.0
参数说明
| 参数 | 作用 |
|---|---|
--network mysql-net |
让 slave 可通过容器名访问 |
-p 3306:3306 |
本地调试方便 |
2️⃣ 进入 Master MySQL
powershell
docker exec -it master mysql -uroot -p
3️⃣ 检查 Master 配置
sql
SHOW VARIABLES LIKE 'server_id';
SHOW VARIABLES LIKE 'log_bin';
SHOW VARIABLES LIKE 'binlog_format';
期望结果:
server_id≠ 0log_bin = ONbinlog_format = ROW
Docker 官方 MySQL 8 镜像默认已开启 binlog
4️⃣ 创建复制账号
sql
CREATE USER 'reader'@'%' IDENTIFIED BY 'reader';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'reader'@'%';
FLUSH PRIVILEGES;
5️⃣ 获取 binlog 位点(非常重要)
sql
SHOW MASTER STATUS;
示例:
File: mysql-bin.000003
Position: 881
必须记录这两个值
六、启动 MySQL Slave
1️⃣ 启动容器
powershell
docker run -d `
--name slave `
--network mysql-net `
-e MYSQL_ROOT_PASSWORD=root `
-p 3307:3306 `
mysql:8.0
2️⃣ 进入 Slave MySQL
powershell
docker exec -it slave mysql -uroot -p
3️⃣ 配置复制源(MySQL 8 写法)
sql
STOP REPLICA;
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = 'master',
SOURCE_PORT = 3306,
SOURCE_USER = 'reader',
SOURCE_PASSWORD = 'reader',
SOURCE_LOG_FILE = 'mysql-bin.000003',
SOURCE_LOG_POS = 881;
START REPLICA;
4️⃣ 查看复制状态
sql
SHOW REPLICA STATUS\G
正常状态:
Replica_IO_Running: Yes
Replica_SQL_Running: Yes
七、一个必踩的大坑(重点)
❗ 问题现象
-
主库创建表
-
从库
Replica_SQL_Running直接变No -
报错:
Last_Errno: 1049
Unknown database 'test_sync'
❗ 原因分析(非常重要)
binlog 会同步 SQL,而不是帮你创建数据库
-
Master 中执行了:
sqlUSE test_sync; CREATE TABLE ... -
但 Slave 中并不存在 test_sync 这个数据库
-
SQL 回放失败,复制线程停止
✅ 正确解决方式
只在 Slave 上创建数据库(不要建表)
sql
CREATE DATABASE test_sync;
START REPLICA;
八、数据同步验证流程
1️⃣ 在 Master 操作数据
sql
CREATE DATABASE test_sync;
USE test_sync;
CREATE TABLE t_user (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(64),
age INT
);
INSERT INTO t_user(username, age) VALUES ('alice', 18);
2️⃣ 在 Slave 验证
sql
USE test_sync;
SELECT * FROM t_user;
如果能看到数据:
+----+----------+-----+
| id | username | age |
+----+----------+-----+
| 1 | alice | 18 |
+----+----------+-----+
🎉 主从复制成功
九、常见问题排查总结
1️⃣ Replica_IO_Running: Connecting
原因:
- 不在同一个 Docker 网络
SOURCE_HOST写成localhost- 端口错误
验证网络:
powershell
docker inspect master --format "{{json .NetworkSettings.Networks}}"
docker inspect slave --format "{{json .NetworkSettings.Networks}}"
2️⃣ Replica_SQL_Running: No
原因:
- 数据库不存在
- 表结构冲突
- 手动在 Slave 建过表
排错命令:
sql
SHOW REPLICA STATUS\G
SELECT *
FROM performance_schema.replication_applier_status_by_worker\G;
十、总结
✔ Docker + MySQL 主从并不复杂
❌ 难点在 细节和顺序
关键点总结:
- 主从必须同一 Docker 网络
- Slave 不会自动建库
- 只在 Master 写数据
- 错误一定要看
Last_Error