MySQL 8.0 双向复制需手动配置两套互为 master/slave 的链路,关键参数包括:server-id 全局唯一、log-bin 开启、gtid_mode=ON、log_slave_updates=ON、auto-increment-increment 与 offset 成对设置以避免主键冲突。

MySQL 8.0 双向复制(Master-Master)不是开个开关就能用的,必须手动配两套互为 master/slave 的链路,且 auto_increment_increment 和 auto_increment_offset 不设对,写冲突会直接丢数据。
my.cnf 必须配齐的 5 个关键参数
双主不是“互相当主库”这么简单,每个节点既要生成 binlog,又要执行对方的 binlog,所以配置必须双向兼容:
-
server-id必须全局唯一(比如 NodeA=1,NodeB=2),否则复制线程拒绝启动 -
log-bin必须开启,路径可自定义,但建议用绝对路径如/var/log/mysql/mysql-bin.log -
gtid_mode = ON+enforce_gtid_consistency = ON强制启用 GTID,避免基于 file/pos 的手工定位出错 -
log_slave_updates = ON—— 这是双向复制的核心:从库收到的变更,也要写进自己的 binlog,才能继续转发给另一端 -
auto_increment_increment和auto_increment_offset必须成对设置:两节点都设auto_increment_increment = 2,NodeA 设auto_increment_offset = 1,NodeB 设auto_increment_offset = 2;否则 INSERT 不指定 ID 时必然主键冲突
CREATE USER 和 CHANGE MASTER TO 容易漏掉的细节
复制用户不是建一次就行,两个节点都要建,且权限、密码、host 必须完全一致,否则一端能连,另一端连不上:
- 用户 host 推荐用
'repl'@'%',避免因 IP 变动或 DNS 解析失败中断复制 - 执行
CHANGE MASTER TO时,MASTER_AUTO_POSITION = 1是必须的(GTID 模式下不能用MASTER_LOG_FILE/MASTER_LOG_POS) - 如果之前启过复制又重配,务必先在两端都执行
STOP SLAVE; RESET SLAVE ALL;,否则残留 relay log 或 gtid_executed 会导致 START SLAVE 报错 - 密码里含特殊字符(如
!、$)时,shell 命令行执行CHANGE MASTER TO会被 shell 截断,建议在 MySQL CLI 里粘贴执行
验证复制是否真通:别只看 Slave_IO_Running
SHOW SLAVE STATUS\G 输出里,Slave_IO_Running: Yes 和 Slave_SQL_Running: Yes 都为 Yes 只代表线程活着,不代表数据在同步。真正要盯的是:
-
Seconds_Behind_Master:应为 0 或稳定小数值(网络延迟导致的短暂波动除外) -
Retrieved_Gtid_Set和Executed_Gtid_Set:两者应完全一致,否则说明 SQL 线程卡在某条事务上 - 手动测试:在 NodeA 插入一条带自增 ID 的记录,立刻去 NodeB 查;再在 NodeB 插入一条,回 NodeA 查——两次都得存在才算通
- 常见假成功:
Slave_SQL_Running: Yes但Seconds_Behind_Master持续增长,大概率是某条 DDL(如 ALTER TABLE)在另一端执行失败,被 SQL 线程跳过,需查Last_SQL_Error
为什么半同步插件装了也不生效?
装了 rpl_semi_sync_master 和 rpl_semi_sync_slave 插件,设了 rpl_semi_sync_master_enabled = 1,但 SHOW VARIABLES LIKE 'rpl_semi_sync%' 显示 rpl_semi_sync_master_status 仍是 OFF,原因通常是:
- 插件名拼错:
semisync_master.so在某些发行版中实际是semisync_master.so(无下划线),而 CentOS 8+ 默认用mysql-router-community包,插件路径可能在/usr/lib64/mysql/plugin/而非/usr/lib/mysql/plugin/ - 没重启 mysqld:插件加载后,必须重启服务才能让
rpl_semi_sync_master_status变为 ON - 从库没启用半同步:仅主库设
rpl_semi_sync_master_enabled = 1不够,从库也得设rpl_semi_sync_slave_enabled = 1并重启,否则主库检测不到 ACK - GTID 模式下,半同步对事务提交的影响更明显:若超时未收 ACK,事务会回滚并报错
ERROR 1794 (HY000),而不是静默降级为异步
最麻烦的不是配置步骤,而是脑裂——网络抖动几秒,两端同时写入,GTID 冲突导致复制中断。这种问题不会在 SHOW SLAVE STATUS 里直接报错,得靠定期比对 SELECT UUID(), @@server_uuid 和 SELECT @@gtid_executed 才能发现端倪。











