必须配对设置auto_increment_increment和auto_increment_offset并校准auto_increment值,因offset仅定起点、increment才定步长,单设offset无效;双节点需increment=2、主offset=1(生成1,3,5…)、从offset=2(生成2,4,6…);insert...select无order by会导致主从插入顺序不同而id错位;replace into在5.7中主从自增行为不一致,8.0已修复。

自增主键不一致不是复制“出错了”,而是 MySQL 自增机制和复制模式共同作用下的确定性结果——只要配置没对齐、初始化没校准、或语句本身非确定,冲突就一定会发生。
auto_increment_offset 单独设置为什么无效
很多人在 my.cnf 里只加了 auto_increment_offset = 2 就以为 ID 不会撞,结果一写就报 Duplicate entry 'X' for key 'PRIMARY'。因为 auto_increment_offset 只决定第一个值,后续仍按默认步长 +1 递增。两台机器都设 offset = 1、increment = 1,都会生成 1、2、3……同步时必然冲突。
真正起作用的是二者的绑定关系:offset 定起点,increment 定间隔,缺一不可。
- 双节点必须配对设
auto_increment_increment = 2,主库offset = 1(生成 1,3,5…),从库offset = 2(生成 2,4,6…) -
offset必须在 1 到increment范围内(含),否则 MySQL 启动时静默重置为 1 - 配置必须写进
my.cnf并重启生效;SET GLOBAL只影响新连接,复制线程可能还在用旧值
INSERT ... SELECT 初始化时主从顺序不同
当用 INSERT INTO t1 SELECT ... FROM t2 批量初始化数据时,主从表的行数可能一致,但每行的 id 值完全不同——因为 SELECT 结果集无显式 ORDER BY,MySQL 不保证返回顺序,主从执行计划、索引选择、缓冲区状态稍有差异,就会导致插入顺序不同,自增值分配路径彻底分叉。
典型现象:主库生成 id=1→10,从库生成 id=1→5,再跳到 11→15,中间空洞+错位。
- 修复不能靠“等同步追平”,必须手动比对各节点
SELECT MAX(id) FROM tbl - 导入前应在源库加
ORDER BY强制顺序,或改用mysqldump --order-by-primary - 如果已发生错位,需停写、取所有节点最大
MAX(id)、+1 后统一执行ALTER TABLE ... AUTO_INCREMENT = N
REPLACE INTO 或 INSERT ... ON DUPLICATE KEY UPDATE 导致主从自增值脱节
在 MySQL 5.7 及更早版本中,REPLACE INTO 遇到唯一键冲突时,主库会先删后插,AUTO_INCREMENT 值照常增长;但从库 binlog 记录的是 UPDATE(因 row 格式下实际变更被优化),不触发自增,导致从库的 AUTO_INCREMENT 值长期低于主库。主从切换后,新主库继续从旧值起步,立刻撞上已有 ID。
- MySQL 8.0+ 已修复该行为,主从自增逻辑统一
- 5.7 环境下应避免
REPLACE INTO和INSERT ... ON DUPLICATE KEY UPDATE用于带自增主键的表 - 若已存在脱节,不能只查
SHOW CREATE TABLE,必须执行SELECT MAX(id)并人工修正
最危险的盲区是:你以为“复制没报错=数据一致”,但自增 ID 的错位不会触发 SQL 线程中断,它安静地埋着雷,直到主从切换或跨库写入那一刻才爆炸。











