auto_increment_increment 和 auto_increment_offset 必须成对配置并写入 my.cnf 的 [mysqld] 段后重启 mysqld,单独设置或运行时修改无效;双主下 A 设 increment=2+offset=1 生成奇数,B 设 increment=2+offset=2 生成偶数,避免主键冲突,但 UPDATE/DELETE 冲突仍需应用层控制。

auto_increment_increment 和 auto_increment_offset 必须成对设,单改一个没用
只设 auto_increment_increment = 2 而不设 auto_increment_offset,两台主库仍会从 1 开始生成 1、2、3……一同步就报 ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'。真正起作用的是组合:A 节点设 auto_increment_increment = 2 + auto_increment_offset = 1 → 生成 1、3、5…;B 节点设 auto_increment_increment = 2 + auto_increment_offset = 2 → 生成 2、4、6…。两者缺一不可。
配置必须写进 my.cnf 的 [mysqld] 段并重启 mysqld
SET GLOBAL auto_increment_increment = 2 看似执行成功,但复制线程启动时已按配置文件初始化计数器,运行时改无效;且 MySQL 8.0 不支持热重载该参数。正确做法是:
- 编辑
/etc/my.cnf或/etc/mysql/my.cnf - 在
[mysqld]段下添加:[mysqld] auto_increment_increment = 2 auto_increment_offset = 1 server-id = 1 log-bin = mysql-bin binlog-format = ROW log_slave_updates = ON
- 另一节点仅改
auto_increment_offset = 2和server-id = 2 - 执行
systemctl restart mysqld(不能只reload)
验证是否生效:连上后执行 SHOW VARIABLES LIKE 'auto_increment%';,必须看到实际值而非默认的 1。
已有数据时,offset 要避开当前最大 ID,但不用重排历史
该配置只影响后续新插入行,不修改已有记录。但若 A 节点表中当前最大 id 是 99,你设 auto_increment_offset = 1,它下次插入是 101(因为 99+2=101,且 101 ≡ 1 mod 2),安全;但如果 B 节点当前最大 id 是 100,设 offset = 2 后下一条是 102,也安全。关键不是“从 offset 开始”,而是“下一个值 = max(id) + increment”,且必须满足 (next_id - offset) % increment == 0。
双主只是防 INSERT 冲突,UPDATE/DELETE 仍需应用层控制
auto_increment_increment 和 auto_increment_offset 只解决主键重复导致的复制中断,完全不管并发 UPDATE 或 DELETE 导致的数据覆盖。比如两端同时执行 UPDATE accounts SET balance = balance + 100 WHERE id = 123,结果取决于 binlog apply 顺序,最终余额可能只加一次。真正要稳住双主,还得:
- 禁用应用直连双主自动写入
- 按业务或分片规则路由写请求(如 user 表全走 A,order 表全走 B)
- 所有 UPDATE 加幂等条件:
WHERE version = ? AND updated_at = ? - 物理删除改为软删:
UPDATE ... SET is_deleted = 1
参数配得再准,只要应用往同一行并发写,数据一致性就靠不住——这点最容易被忽略。


















