1062错误是主从数据实质不一致的明确信号,表明从库已存在某记录(如id=120383),主库又发送重复insert/replace触发唯一键冲突;强行跳过仅恢复sql线程却扩大数据偏差,gtid模式下sql_slave_skip_counter已被弃用,须用set gtid_next注入空事务跳过,且必须溯源排查应用幂等、手动修数或备份导入等问题。

1062 错误不是“跳过就能继续跑”,而是主从数据已实质不一致的明确信号。它说明从库当前已有某条记录(比如 id = 120383),但主库又发来一条 INSERT 或 REPLACE,触发了 Duplicate entry '120383' for key 'PRIMARY'。强行跳过只是让 SQL 线程恢复运行,但两边数据差得更远了。
为什么 pt-slave-restart 常常治标不治本
这个工具本质是自动执行 SET GLOBAL sql_slave_skip_counter = 1 并重启 SQL 线程,但它无法判断:
- 这条冲突语句在主库是否本不该执行(比如开发误操作、测试残留)
- 从库多出的那条记录是否影响业务(比如是脏数据,还是关键状态)
- 跳过后下一个事务会不会又在别的表爆 1062(常见于
auto_increment_offset不一致或 binlog_format=STATEMENT 下的非确定性函数)
更关键的是:pt-slave-restart 在 GTID 模式下默认失效——因为 sql_slave_skip_counter 已被 MySQL 8.0.23+ 彻底弃用,执行会直接报错 ERROR 1858 (HY000): sql_slave_skip_counter can not be set when the server is running with @@GLOBAL.GTID_MODE = ON。
手动删除冲突行前必须确认三件事
比起盲目跳过,定位并清理从库“多余”的那条记录更可控。但操作前务必验证:
- 查主库真实数据:
SELECT * FROM tbl WHERE id = 120383;—— 确认主库确实有且仅有一条 - 查从库当前值:
SELECT * FROM tbl WHERE id = 120383;—— 对比字段内容,看是否只是部分字段不一致(如log_result字段值不同),这种场景更适合用REPLACE INTO或UPDATE同步,而非 DELETE - 关掉写入:
SET sql_log_bin = 0;再执行DELETE FROM tbl WHERE id = 120383;,避免该删除动作又被同步回主库
GTID 模式下跳过事务的实操要点
如果你确认要跳过(比如已人工修复从库数据,只差一个事务卡住),必须走 GTID 注入空事务流程:
- 先停复制:
STOP REPLICA; - 从
SHOW SLAVE STATUS\G的Last_SQL_Error里提取 GTID,例如3e11fa47-71ca-11e1-9e33-c80aa9429562:23 - 注入空事务(顺序不能错):
SET GTID_NEXT = '3e11fa47-71ca-11e1-9e33-c80aa9429562:23';<br>BEGIN;<br>COMMIT;<br>SET GTID_NEXT = 'AUTOMATIC';
- 重启:
START REPLICA;
漏掉 STOP REPLICA 或写错 GTID_NEXT 值,都会导致跳过失败,甚至引发 GTID 集合错乱。
真正麻烦的从来不是怎么跳过 1062,而是为什么同一张表、同一个主键,在主从上会存在两套不同来源的数据。往往查到最后,问题出在应用层没做幂等、DBA 手动修数没关 sql_log_bin、或者备份导入时没禁用并行复制线程。这些细节比命令本身更值得盯紧。











