必须修改配置文件并重启MySQL才能使auto_increment_increment生效;仅SET GLOBAL无效,且须成对设置increment与offset,否则双主写入必触发ERROR 1062。

直接改 SET GLOBAL auto_increment_increment 会失效
很多人执行 SET GLOBAL auto_increment_increment = 2 后就以为配置生效了,结果双主一写还是报 ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'。这是因为 MySQL 复制线程在启动时已按配置文件初始化自增计数器,运行时改全局变量只影响新连接,旧连接和复制线程仍用旧值。MySQL 8.0 不支持热重载该参数,SET GLOBAL 对复制冲突毫无作用。
真正起效的只有写入 /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
另一节点仅改 auto_increment_offset = 2 和 server-id = 2,然后执行 systemctl restart mysqld(不能用 reload)。
必须成对设置 auto_increment_increment 和 auto_increment_offset
只设 auto_increment_increment = 2 而不设 auto_increment_offset,两台主库都会从 1 开始生成 1、2、3……同步瞬间就撞。关键逻辑是:offset 定起点,increment 定间隔,二者绑定才构成完整序列规则。
- A 节点:
auto_increment_increment = 2+auto_increment_offset = 1→ 下一个 ID 是满足(next_id - 1) % 2 == 0的最小值,即 1、3、5… - B 节点:
auto_increment_increment = 2+auto_increment_offset = 2→ 下一个 ID 满足(next_id - 2) % 2 == 0,即 2、4、6… - 若部署三节点双主,应设
increment = 3,各节点offset分别为 1、2、3;且offset必须在 1 到increment范围内,否则 MySQL 启动时静默重置为 1
已有数据时,offset 不决定“从几开始”,而是影响“下一个值”
配置不会重排历史数据,也不强制从 offset 值开始插入。它只控制下一条插入的计算逻辑:next_id = MAX(id) + increment,且必须满足 (next_id - offset) % increment == 0。
例如:
- A 表当前最大
id是 99,设offset = 1、increment = 2→ 下一条是 101(因为 99+2=101,且 (101−1)%2==0) - B 表当前最大
id是 100,设offset = 2、increment = 2→ 下一条是 102((102−2)%2==0) - 但如果 A 表最大
id是 100,却设offset = 2,则下一条仍是 102(不是 2),但 102 已满足条件;若误设offset = 3,MySQL 启动时会把它改成 1
主从切换后不校准 AUTO_INCREMENT 值,必出冲突
从库升主后,它的 AUTO_INCREMENT 值仍沿用旧从库状态,而原主库可能已分配出更高 ID。MySQL 启动时不读 binlog、不查对方状态,只用 SELECT MAX(id) + 1 初始化(5.7 及之前),8.0 虽有优化但仍不跨实例同步计数器。
切换前必须手动校准:
- 在目标从库上执行
SELECT MAX(id) FROM tbl_name - 取所有节点该表的
MAX(id)最大值,再 +1,作为新AUTO_INCREMENT值 - 执行
ALTER TABLE tbl_name AUTO_INCREMENT = N(N 必须严格大于所有节点当前最大 ID) - 验证:
SHOW CREATE TABLE tbl_name,确认AUTO_INCREMENT字段已更新
最易被忽略的是:这个值不是“建议设”,而是“不设就必然冲突”。哪怕只差 1,也会在第一次 INSERT 时触发主键重复,且错误不会延迟出现。


















