ERROR 1062是主从数据已不一致的明确信号,非临时故障;必须先确认gtid_mode状态,GTID开启时sql_slave_skip_counter彻底失效,须用SET GTID_NEXT注入空事务精准跳过,且跳过前必须溯源差异根因并修复。

MySQL主从同步报错 ERROR 1062(Duplicate entry)不是“跳过就能恢复”的临时故障,而是主从数据已实际不一致的明确信号。直接跳过只会让问题沉淀、扩散,后续可能在更多表、更多字段上反复爆发。
确认是否启用 GTID 复制
这是所有操作的前提。执行:SHOW VARIABLES LIKE 'gtid_mode';,若返回 ON,则 sql_slave_skip_counter 已彻底失效,强行设置会报错 ERROR 1858 或 ERROR 1251。
常见误判点:
- 看到
SHOW SLAVE STATUS\G中Executed_Gtid_Set非空,就认为开了 GTID —— 实际可能是旧从库残留值,必须以gtid_mode变量为准 - 主库开 GTID、从库没开,或反之,会导致复制无法启动或中途断裂,
1062往往是连带症状 - GTID 模式下,
slave-skip-errors = 1062在配置文件中写入后重启,仅对新产生的错误生效,对当前卡住的事务无效
GTID 模式下跳过单个事务(精准但高危)
跳过动作本质是“伪造一个已执行过的 GTID”,让复制线程认为该事务已完成。漏掉任一环节都可能导致 GTID 集合错乱、复制永久中断。
操作顺序不可调换:
- 先查出报错事务的完整 GTID:在
SHOW SLAVE STATUS\G的Last_SQL_Error字段里找,形如gtid:3e11fa47-71ca-11e1-9e33-c80aa9429562:23;注意冒号前后不能有空格,大小写需完全一致 - 执行
STOP REPLICA;(MySQL 8.0.22+ 命令已弃用SLAVE语法) -
SET GTID_NEXT = '3e11fa47-71ca-11e1-9e33-c80aa9429562:23';(值必须严格匹配) -
BEGIN; COMMIT;(必须是空事务,不能带任何 DML) SET GTID_NEXT = 'AUTOMATIC';START REPLICA;
关键风险点:如果 GTID_NEXT 值抄错、或 COMMIT 前连接断开,从库将进入不可恢复的 GTID 不一致状态,只能重建从库。
非 GTID 模式下定位 relay_log_pos 跳过(兼容但需手动计算)
适用于 gtid_mode = OFF 且 binlog_format = ROW 的环境。跳过目标不是“跳一条”,而是“跳到下一个事务开头”。
步骤要点:
- 停 SQL 线程:
STOP REPLICA SQL_THREAD; - 从
SHOW SLAVE STATUS\G中提取Relay_Master_Log_File和Exec_Master_Log_Pos(这是主库 binlog 中出错事务的结束位置) - 用
mysqlbinlog --base64-output=DECODE-ROWS -v /path/to/mysql-bin.0000xx | grep -A 5 -B 5 'your_duplicate_value'定位该事务在 binlog 中的实际起始偏移 - 执行
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.0000xx', MASTER_LOG_POS=yyyyy;,其中yyyyy是下一个事务的起始位置,不是当前事务的结束位置 - 再
START REPLICA;
常见坑:Exec_Master_Log_Pos 是事务结尾,直接跳到这里会重放整个事务,冲突照旧;必须向前或向后翻几行 binlog 找到事务边界。
比跳过更优先做的事:查清数据差异来源
跳过只是应急,真正要花时间的是定位“为什么从库多了一条记录”。高频原因包括:
- 从库未设
read_only = ON或被应用直连写入(检查SHOW GLOBAL VARIABLES LIKE 'read_only';和super_read_only) - 主库
log_slave_updates = OFF,导致级联复制时中间节点无法生成正确 GTID - 主库执行了
INSERT IGNORE或REPLACE INTO,但从库因触发器/约束/SQL_MODE 差异,实际执行为普通INSERT - 应用层幂等逻辑缺失,同一请求在主库成功、重试时又发到从库(尤其跨机房部署时)
验证方式:在从库执行 SELECT * FROM tbl WHERE id = xxx;,对比主库同语句结果;若从库多出数据且确认无业务价值,优先 DELETE 而非跳过 —— 这样既消除了冲突,又保留了 GTID 连续性。


















