mysql 8.0双向主主复制必须手动配置两套互为master/slave链路,关键包括:server-id全局唯一(如1和2)、auto-increment-offset与increment成对错开(如1/2和2/2)、强制gtid+row格式+log_slave_updates=on、replicate-same-server-id=0防循环,且复制用户、网络、权限须双向对称。

MySQL 8.0 的双向主主复制(Master-Master)不是“配完就能用”的功能,它必须手动配两套互为 MASTER/SLAVE 的链路,且 auto_increment_offset 和 auto_increment_increment 错配一丁点,INSERT 就会直接报 Duplicate entry '1' for key 'PRIMARY'。
server-id 和 auto-increment 必须成对错开
两个节点的 server-id 不仅要不同,还不能是默认值 1(尤其 Docker 场景下易撞车)。常见错误是 A 和 B 都设成 1,导致 START SLAVE 直接失败或静默不工作。
- A 节点:
server-id = 1,auto_increment_offset = 1,auto_increment_increment = 2 - B 节点:
server-id = 2,auto_increment_offset = 2,auto_increment_increment = 2 - 如果已有存量数据,务必检查两边主键 ID 是否重叠——比如 A 有 ID=2 的记录,B 又生成了 ID=2,启动复制后立刻卡住
-
innodb_autoinc_lock_mode建议设为0(传统模式),避免并发INSERT ... SELECT时因间隙锁失效导致 offset 错乱
GTID + ROW 格式 + log_slave_updates 是硬性组合
缺一不可。只开 GTID 不开 log_slave_updates,B 收到 A 的变更后不会写进自己的 binlog,A 就永远收不到回传;只开 log_slave_updates 但 binlog_format 不是 ROW,NOW()、UUID() 这类非确定函数在两边执行结果不同,数据必然不一致。
- my.cnf 中必须显式写:
gtid_mode = ON、enforce_gtid_consistency = ON、binlog_format = ROW、log_slave_updates = ON - 不要依赖 MySQL 8.0 默认值:
binlog_format在多数发行版中仍是STATEMENT,必须手动覆盖 - 改完配置必须重启
mysqld,并验证:SELECT @@binlog_format;返回ROW,SELECT @@gtid_mode;返回ON
replicate-same-server-id = 0 是防循环复制的生死线
这是最容易被忽略、但最致命的一条。不设它,A 写入 → B 同步 → B 把这条日志再发回 A → A 二次执行 → 主键冲突 / 计数翻倍 / relay log 爆满。错误日志里往往只显示模糊的 Relay log read failure,根本看不出是回环。
- 两台机器的 my.cnf 都必须加:
replicate-same-server-id = 0(MySQL 8.0+ 语法,不是replicate_same_server_id) - 不能靠
binlog-ignore-db或防火墙代替——它们不识别事件来源server-id - 如果之前启过复制又重配,先在两端都执行:
STOP SLAVE; RESET SLAVE ALL;,否则残留的 GTID 位点会导致START SLAVE报错
复制用户和网络连通性必须双向对称
双主意味着每台机器既是主又是从,所以每台都要创建对方连接自己所需的复制用户,且权限、密码、host 完全一致。常见坑是 A 创建了 'repl'@'B_IP',但 B 没建 'repl'@'A_IP',或者防火墙只开了 A→B 的 3306,没开 B→A。
- 推荐用
'repl'@'%',避免 IP 变动或 DNS 解析失败中断复制 - 密码含
!、$等 shell 特殊字符时,别在命令行里执行CHANGE REPLICATION SOURCE TO,直接进 MySQL CLI 粘贴 - Docker 环境注意挂载配置文件权限:
chmod 644,否则 MySQL 启动时会警告并忽略该配置 - SELinux 若开启,需确认
mysqld_can_network_connect为on,否则连接会被静默拒绝
真正难的从来不是敲几行 CHANGE REPLICATION SOURCE TO,而是想清楚:哪些表允许双写、哪些字段必须加时间戳或版本号校验、哪些业务(比如库存扣减)必须强制路由到单中心——这些决策不在配置文件里,而在你每次 INSERT 和 UPDATE 的业务逻辑中。











