主从同步中断时出现duplicate entry错误,根本原因是自增id未对齐,必须停写、校准max(id)+1、配对设置auto_increment_increment与offset;show slave status的exec_master_log_pos仅表示binlog位置追平,不反映自增计数器状态,gtid模式下该问题同样存在。

主从同步中断时出现 Duplicate entry 'X' for key 'PRIMARY',基本就是自增ID没对齐——不是修同步线程能解决的,得立刻停写、校准值、配对改配置。
为什么 SHOW SLAVE STATUS 显示已追平却还在报冲突?
因为 Exec_Master_Log_Pos 只表示 binlog 位置追上了,不表示 AUTO_INCREMENT 计数器已对齐。MySQL 启动时用 SELECT MAX(id) + 1 初始化该值(5.7 及之前),不读 binlog,也不看对方状态。GTID 模式下同样不管 ID 怎么生成,auto_increment_offset 和 auto_increment_increment 仍是各自独立配置。
常见现象:新主库刚切完,第一笔插入就报错;或者从库 SQL 线程卡在某条 INSERT 上,错误日志里反复出现相同 ID 冲突。
必须立刻执行的三步校准操作
别先想着跳过错误或重放 binlog——那只是掩盖问题。正确顺序是:
- 暂停所有写入(尤其是应用层双写、跨库直连)
- 查出所有节点上该表的
MAX(id),取最大值 +1 作为目标值 - 在即将升主的从库上执行:
ALTER TABLE tbl_name AUTO_INCREMENT = N;(N 必须大于所有节点当前最大 ID) - 确认生效:
SHOW CREATE TABLE tbl_name;查看输出中AUTO_INCREMENT是否已更新
注意:仅靠 mysqldump --auto-commit 或导入时加 --insert-ignore 不会更新表元数据里的当前计数器,后续插入仍会撞。
auto_increment_increment 和 auto_increment_offset 必须配对设
只改 offset 没用,increment 不匹配,还是按默认步长 +1 递增。规则很简单:
- 双节点:统一设
auto_increment_increment = 2,主库offset = 1(生成 1,3,5…),从库offset = 2(生成 2,4,6…) - 三节点可升主场景:设
increment = 3,三台分别设offset = 1/2/3,且offset必须在 1 到increment之间,否则 MySQL 启动时静默重置为 1 - 配置必须写进
my.cnf并重启生效;SET GLOBAL只影响新连接,复制线程可能还在用旧值
MySQL 8.0+ 的 MGR 组复制自动处理自增逻辑,但传统异步/半同步复制仍要手动配。
最容易被忽略的三个点
一是只校准了本机 MAX(id),没查其他节点,导致新 AUTO_INCREMENT 值仍小于某台从库已存在的 ID;二是改了配置但没重启,或只执行了 SET GLOBAL,复制线程继续用旧步长;三是应用有历史跨库写入,但没清理或归档这些脏数据,校准后依然会撞。











