MySQL双主迁移后冲突根源在于自增参数未对齐且复制参数缺失:必须配对设置auto_increment_offset与increment,同时启用innodb_autoinc_lock_mode=0、log_slave_updates=ON及唯一server-id,并校准表级AUTO_INCREMENT值,应用层还需路由分片与幂等控制。

迁移后多主冲突,根本不是“步长设错了”,而是新旧环境的 auto_increment_increment 和 auto_increment_offset 没对齐,且漏配了关键复制参数。光改步长,等于只系了鞋带,忘了穿鞋。
检查当前各节点的自增配置是否真正生效
迁移后很多人只改了配置文件,但没验证是否加载成功。MySQL 会优先读取运行时值,而非配置文件内容。
- 连上每台节点,执行
SELECT @@auto_increment_increment, @@auto_increment_offset;—— 必须看到预期值(如双主:A 是 1/2,B 是 2/2) - 如果值仍是默认的
1/1,说明配置没生效:可能是写到了[client]段、没加SET PERSIST(MySQL 8.0+),或根本没重启 mysqld - 新建测试表
CREATE TABLE test_inc (id INT PRIMARY KEY AUTO_INCREMENT),分别在两台插入 3 行,查SELECT id FROM test_inc;若出现连续 ID(如 1,2,3),说明 offset 完全失效
必须同步补齐三项复制级参数,否则步长形同虚设
仅调 auto_increment_offset 和 auto_increment_increment,解决不了 INSERT SELECT、LOAD DATA、并发写同一行等真实场景。以下三项缺一不可:
-
innodb_autoinc_lock_mode = 0:双主下必须设为传统锁模式,否则批量插入可能跳号,导致后续 INSERT 碰撞 -
log_slave_updates = ON:关闭它,relay log 的变更不会写入本机 binlog,双向复制断裂,GTID 或校验工具全部失灵 -
server-id全局唯一(如 A=1,B=2):MySQL 靠它识别并过滤回环事件;若两台都是 1,A→B→A 的变更会被重复执行,ID 冲突只是表象,数据逻辑早已错乱
迁移后务必重置表级 AUTO_INCREMENT 值
迁移过程常伴随 dump/reload 或逻辑导入,容易让表的 AUTO_INCREMENT 值停留在旧偏移位置,和新步长规则不兼容。
- 执行
SHOW CREATE TABLE your_table,看输出里AUTO_INCREMENT=xxx是否落在合法序列内(例如双主 A 设了 offset=1/increment=2,当前值却为 100,而 100 是偶数 → 下次 INSERT 就撞 B 的序列) - 安全做法:先查当前最大 ID:
SELECT MAX(id) FROM your_table,再按步长规则向上取整,用ALTER TABLE your_table AUTO_INCREMENT = N手动设到下一个合法值(如最大是 99,A 节点应设为 101) - 注意:该操作需在所有节点都停写时执行,否则可能被并发 INSERT 干扰
别信“配置完就万事大吉”,应用层路由才是冲突分水岭
自增步长只防 INSERT 主键碰撞,不防 UPDATE/DELETE 覆盖、不防应用同时写同一行、不防业务逻辑冲突。迁移后最容易忽略的是写入路径是否收敛。
- 禁止应用直连双主做轮询或随机写入——这等于主动把冲突逻辑交给数据库兜底
- 必须按业务维度拆分写入:比如 user 表固定走 A,order 表固定走 B;或按
user_id % 2分片,奇数写 A,偶数写 B - 所有非 INSERT 操作必须幂等:
UPDATE ... WHERE id = ? AND version = ?,失败即告警,不盲目覆盖
配置能让你的数据库不崩,但只有应用知道哪条数据该去哪台库——这个决策点,从来不在 my.cnf 里。


















