双主热备必须防循环复制,否则A写入→B同步→B再发回A→A重复执行,导致主键冲突、数据翻倍、SQL线程中断;须配对设置auto-increment-increment=2与auto-increment-offset=1(A)/2(B),并启用replicate-same-server-id=0阻断回环。

为什么双主热备必须防循环复制
双主热备本质是两台 MySQL 互为 master 和 slave,各自写入都会被对方同步。如果不加控制,A 写一条数据 → B 同步执行 → B 又把这条执行记录发回 A → A 再同步执行……无限套娃,最终导致主键冲突、数据翻倍、SQL 线程报错 Slave_SQL_Running: No,甚至数据库 crash。
auto-increment-offset 和 auto-increment-increment 必须配对设
这是防主键冲突最基础也最关键的一步。只设一个没用,必须两个参数协同生效:
-
auto-increment-increment设为 2(或大于等于节点数的整数),表示自增步长 -
auto-increment-offset在 A 上设为 1,在 B 上设为 2(偏移值必须互不重叠且 - 重启 mysqld 后才生效,
SET GLOBAL不起作用 - 如果已有表含自增主键,需手动检查并调整
ALTER TABLE t AUTO_INCREMENT = N起始值,避免新旧值重叠
启用 log-slave-updates 并关闭 read_only 的副作用
双主要求从库也能写入(否则无法互为主),但默认 read_only=ON 会阻止用户写入,而 log-slave-updates=ON 是让从库把同步来的变更再写进自己的 binlog——这两者必须同时打开,否则复制链断裂:
-
log-slave-updates=ON:强制从库将 relay log 中执行的 SQL 写入本地 binlog,否则 B 收到 A 的变更后不记录,就无法再发给 A -
read_only=OFF:允许应用直接写 B;但注意:仅 root 或有SUPER权限的用户可绕过该限制,普通账号仍会被拒绝 - 务必禁用
replicate-same-server-id(默认 OFF),否则同一 server-id 的 binlog 会被忽略,导致循环中断失败
用 replicate-ignore-db 或 replicate-do-table 过滤系统库和复制元数据
即使开了 log-slave-updates,也不能无差别转发所有日志。MySQL 自身维护的 mysql 库(含 slave_master_info、slave_relay_log_info)若被双向同步,会导致位置信息错乱、复制中断:
- 在两台服务器上都配置:
replicate-ignore-db=mysql、replicate-ignore-db=information_schema、replicate-ignore-db=performance_schema - 如只同步业务库,推荐更安全的白名单方式:
replicate-do-db=your_app_db - 避免用
binlog-ignore-db控制主库日志生成——它不防循环,只减少日志体积;真正防循环靠的是从库端的过滤
循环复制不是“开了双主就会自动发生”的问题,而是配置漏项的必然结果。最容易被跳过的其实是 log-slave-updates 和 replicate-ignore-db=mysql 这两项,一漏就卡在 Seconds_Behind_Master: NULL 或反复报错 Could not execute Write_rows event on table mysql.slave_master_info。


















