必须先执行show variables like 'gtid_mode'确认模式,gtid开启时sql_slave_skip_counter已弃用,须用stop replica→set gtid_next→begin;commit→set gtid_next='automatic'→start replica五步注入空事务跳过,漏一步或抄错gtid将导致复制永久中断。

MySQL主从复制出现 Duplicate entry 错误(错误码 1062),不是同步机制出了问题,而是主从数据已经不一致了——它是一个结果,不是原因。
为什么SHOW SLAVE STATUS显示已追平却还在报错
因为 Exec_Master_Log_Pos 只表示 binlog 位置追上了,不反映 AUTO_INCREMENT 计数器、手动插入记录、或触发器生成的数据状态。从库启动时用 SELECT MAX(id) + 1 初始化自增值,不读主库状态,也不同步计数器。GTID 模式下同样如此:GTID 保证事务有序执行,但不保证自增 ID 对齐。
- 常见现象:切主后第一笔 INSERT 就报
Duplicate entry '5' for key 'PRIMARY' - 误判点:看到
Seconds_Behind_Master: 0就以为数据一致,其实只是日志位置对齐 - 验证方法:在主从两边分别执行
SELECT MAX(id) FROM tbl_name,对比结果
SET GLOBAL sql_slave_skip_counter = 1 为什么经常失效或报错
这个命令在 MySQL 8.0.23+ 默认开启 GTID 后已被弃用,强行执行会直接报 ERROR 1858 或 ERROR 1251;即使在非 GTID 模式下,它也只对 binlog_format = STATEMENT 稳定有效,而默认是 ROW 格式——此时执行会报 ERROR 1374,且跳过的不是当前出错事务,而是“下一条事件”,极易引发后续错位。
- GTID 模式下必须用
SET GTID_NEXT注入空事务,漏一步或抄错一位字符(比如大小写、空格、冒号)都会导致 GTID 集合永久错乱 - 非 GTID 模式下,更稳妥的做法是停 SQL 线程,用
mysqlbinlog解析Relay_Master_Log_File和Exec_Master_Log_Pos定位冲突语句,再决定删脏数据还是手动修复 -
slave-skip-errors = 1062需重启生效,线上不可行,还会掩盖所有 1062,让不一致静默扩大
怎么确认是不是 GTID 模式(关键前置动作)
别看 Executed_Gtid_Set 非空就认为开了 GTID——那可能是旧从库残留值。唯一权威判断方式是查变量:
SHOW VARIABLES LIKE 'gtid_mode';
- 返回
ON:必须走 GTID 跳过流程(STOP REPLICA→SET GTID_NEXT→BEGIN; COMMIT;→START REPLICA) - 返回
OFF:才能考虑sql_slave_skip_counter或基于 position 的CHANGE MASTER TO - 主库开 GTID、从库没开,或反之,会导致复制无法启动或卡在 1062 无法跳过
跳过只是临时止血,真正要盯紧的是写入源头
1062 是主从数据已不一致的明确信号,不是孤立错误。跳过一次,下次大概率在别的表、别的字段上爆发。尤其注意以下场景:
- 应用层双写(同时往主库和从库发 INSERT)
- 人为在从库执行
INSERT或UPDATE(未设read_only=ON) - 主库用了
INSERT ... ON DUPLICATE KEY UPDATE,但从库因数据差异被当成纯INSERT执行 - 备份恢复时没清空目标库,或 mysqldump 导出时没加
--skip-triggers,触发器二次插入
最危险的操作,是把跳过当成常规手段。GTID 下伪造事务稍有不慎,从库就再也无法自动恢复——它不会报错,只会默默跳过后续所有事务。











