必须先执行SHOW VARIABLES LIKE 'gtid_mode'确认模式:返回ON则为GTID模式,须用STOP REPLICA→SET GTID_NEXT→BEGIN;COMMIT→SET GTID_NEXT='AUTOMATIC'→START REPLICA五步注入空事务跳过;返回OFF才可用传统方式,且跳过仅为临时恢复,须立即查根源、清脏数据、校验一致性。

MySQL 8.0 主从复制报错 ERROR 1062,不是“同步慢了”或“临时卡顿”,而是从库执行某条 INSERT 或 REPLACE 时明确发现主键或唯一键已存在——数据已实质不一致。跳过错误本身不能修复不一致,反而可能让错位扩散。
怎么快速确认是不是 GTID 模式
别看 Executed_Gtid_Set 是否非空,那是旧从库残留值,不可靠。必须执行:
SHOW VARIABLES LIKE 'gtid_mode';
返回 ON 就是 GTID 模式;返回 OFF 才能用传统 position 方式。常见误判点:
-
SET GLOBAL sql_slave_skip_counter = 1报ERROR 1251或ERROR 1858→ 说明 GTID 已启用,该命令彻底失效 - 主库开 GTID、从库没开,或反之 → 复制启动失败或中途断裂,
1062往往是连带症状 - MySQL 8.0.23+ 默认开启 GTID,新部署几乎全是
gtid_mode = ON
GTID 模式下跳过冲突事务的唯一合法路径
本质是“伪造一个已执行的 GTID”,让 SQL 线程跳过卡点。漏一步、抄错一位、或 COMMIT 前断连,都会导致 GTID 集合永久错乱,只能重建从库。
- 从
SHOW SLAVE STATUS\G的Last_SQL_Error字段提取完整 GTID,例如:3e11fa47-71ca-11e1-9e33-c80aa9429562:23(冒号前后无空格,大小写严格一致) - 停 SQL 线程:
STOP REPLICA;(MySQL 8.0.22+ 推荐用REPLICA,SLAVE已弃用) - 按顺序执行:
SET GTID_NEXT = '3e11fa47-71ca-11e1-9e33-c80aa9429562:23';→BEGIN;→COMMIT;(必须是空事务,不能带任何 DML) - 重置并重启:
SET GTID_NEXT = 'AUTOMATIC';→START REPLICA;
跳过之后必须立刻查清的三件事
跳过只是恢复同步的起点,不是终点。否则几分钟后另一张表又会爆 1062。
- 查根源:用
mysqlbinlog --base64-output=DECODE-ROWS -v解析报错对应 binlog,确认那条INSERT是谁、何时、为何产生;同时在从库执行SELECT * FROM 表名 WHERE 主键 = X;,比对主库是否存在、是否多出一行 - 清脏数据:如果从库存在不该有的记录(如人为误插入),且业务允许,优先
DELETE FROM 表名 WHERE 主键 = X;,再启动复制——比跳过更安全、更可追溯 - 校一致性:跳过或清理后,至少抽样核验关键表:
SELECT COUNT(*), MIN(id), MAX(id) FROM 表名;;或用pt-table-checksum全量比对
为什么手动删冲突行比跳过更可控
比起注入空事务,定位并删除从库“多余”的那条记录风险更低,但操作前必须确认:
- 查主库真实数据:
SELECT * FROM tbl WHERE id = 120383;→ 确认主库确实有且仅有一条 - 查从库当前值:
SELECT * FROM tbl WHERE id = 120383;→ 对比字段内容,看是否只是部分字段不一致(这种场景更适合REPLACE INTO或UPDATE同步) - 关 binlog 写入:
SET sql_log_bin = 0;,再执行DELETE FROM tbl WHERE id = 120383;,避免该删除动作又被同步回主库
真正危险的不是 1062 这个错误码,而是它背后暴露的写入规范缺失:应用双写主库没做幂等、从库被误开 read_only = OFF、auto_increment_offset 主从配错、或历史导入遗漏。这些点一旦忽略,修复一次,下次还会在别的表上爆发。


















