一主多从必须为每个从库配置唯一server-id、独立复制账号及初始数据一致;否则新增从库会卡在seconds_behind_master: null或io_thread: connecting状态。

一主多从不是简单复制一遍一主一从配置就能跑通的,核心在于每个从库必须有唯一 server-id、独立的复制账号权限控制、以及初始数据一致性保障——漏掉任一环节,新增从库大概率卡在 Seconds_Behind_Master: NULL 或 IO_THREAD: Connecting 状态。
每个从库的 server-id 必须全局唯一且不能为 0
MySQL 用 server-id 区分集群中每一台节点,主库和所有从库之间不能重复,也不能是 0(否则启动失败或被忽略)。常见错误是把多个从库都设成 server-id=2,导致后启动的从库无法注册或覆盖前一个。
- 推荐用 IP 尾段映射:主库
server-id=100,从库1server-id=101,从库2server-id=102…… - 修改后必须重启 MySQL:
systemctl restart mysqld(Linux)或重启服务(Windows) - 验证方式:
SELECT @@server_id;,不是看配置文件,而是看运行时值
主库要为每个从库单独授权或放宽 host 限制
复制账号的 host 部分决定了它能从哪台机器连接。如果主库只创建了 'repl'@'192.168.1.101',那新加入的 192.168.1.102 从库会直接报错 ERROR 1045 (28000): Access denied for user 'repl'@'192.168.1.102'。
- 最稳妥做法:为每个从库创建独立账号,例如
'repl101'@'192.168.1.101'、'repl102'@'192.168.1.102' - 简化做法(测试环境可用):
'repl'@'%',但需确保网络层已限制访问来源(如防火墙只放行内网 IP) - 授权后务必执行
FLUSH PRIVILEGES;,否则权限不生效
新增从库必须与主库初始数据一致,不能跳过这步
很多人以为只要 CHANGE MASTER TO 就能自动同步,其实它只负责后续 binlog 拉取——如果从库已有脏数据或表结构不一致,SQL 线程会直接报错中断(比如 Duplicate entry 或 Table doesn't exist)。
- 小数据量(mysqldump -u root -p --all-databases --single-transaction --master-data=2 > init.sql,再导入从库
- 大数据量:优先从**已同步的从库**克隆数据(
rsync -av /var/lib/mysql/ user@192.168.1.102:/var/lib/mysql/),避免给主库加压 - 无论哪种方式,导入后都要在从库执行
RESET SLAVE ALL;清理旧 relay log 和复制位点
CHANGE MASTER TO 的 MASTER_LOG_FILE 和 MASTER_LOG_POS 必须来自同一时刻快照
主库上 SHOW MASTER STATUS; 返回的 File 和 Position 是瞬时值。如果导出数据后主库又写了新记录,而你用的是导出前查到的位点,从库启动后就会漏掉中间变更,甚至因主键冲突直接停止复制。
- 正确顺序:锁表 → 查位点 → 导出 → 解锁 → 在从库执行
CHANGE MASTER TO(使用刚查到的位点) - 锁表命令:
FLUSH TABLES WITH READ LOCK;(主库),导出完成后执行UNLOCK TABLES; - MySQL 8.0+ 若启用 GTID,可改用
MASTER_AUTO_POSITION = 1,跳过手动指定位点,但要求主从都开启gtid_mode=ON
最容易被忽略的是中继日志路径和权限问题:多个从库共用默认 relay-log 名称时,若未显式指定不同文件名,重启后可能互相覆盖;另外 /var/lib/mysql/ 目录属主必须是 mysql 用户,否则从库启动时报错 Can't create/write to file。











