必须先确认复制模式:有executed_gtid_set且非空→gtid模式,须用set gtid_next+begin;commit跳过;否则为传统模式,可用sql_replica_skip_counter或change replication source to定位跳过。

不能一概而论“跳过错误事务”,必须先确认复制模式(GTID 还是传统 position)、错误类型(1032/1062/DDL)、以及你是否愿意承担数据不一致风险。 直接执行 SET GLOBAL sql_slave_skip_counter = 1 可能跳错、漏跳,甚至在 MySQL 8.0.23+ 被忽略或报 warning。
怎么判断该用 GTID 还是 position 方式跳过?
看 SHOW REPLICA STATUS\G 输出里有没有 Executed_Gtid_Set 字段且非空。有 → GTID 模式;没有或为空 → 传统复制(Auto_Position=0)。前者必须用 GTID 方式跳,后者才可能用 sql_replica_skip_counter 或 CHANGE REPLICATION SOURCE TO。
- GTID 模式下
sql_replica_skip_counter完全无效,设了也白设 - 传统模式下用 GTID 方式(如
SET SESSION GTID_NEXT)会报错:ERROR 1840 (HY000): GTID_EXECUTED is not empty - MySQL 8.0.26+ 已用
sql_replica_skip_counter替代sql_slave_skip_counter,旧变量仅兼容,不推荐新环境使用
GTID 模式下跳过单个失败事务(比如 1032)
核心是“伪造一个已执行的 GTID”,让从库认为这个事务已经完成。操作必须在 STOP REPLICA 后执行,且不能写入 binlog(否则主从 GTID 集合错乱):
- 查出报错事务的 GTID:
Last_IO_Errno和Last_SQL_Error里一般含gtid_set: xxxxx:12345,或从Executed_Gtid_Set推断下一个 - 执行:
SET SESSION GTID_NEXT = 'xxxxx:12345'; - 执行空事务:
BEGIN; COMMIT; - 重置:
SET SESSION GTID_NEXT = AUTOMATIC; START REPLICA;
注意:GTID_NEXT 是 session 级,不能跨连接;若误设成已存在的 GTID,会报错 ERROR 1840;跳完后务必检查 Executed_Gtid_Set 是否包含该 GTID。
传统复制下跳过 1032/1062 错误的实操要点
这类错误本质是数据不一致(从库缺行或主键冲突),跳过只是临时续跑,不是修复。优先考虑补数据或删冲突行,而非跳过:
-
1032(找不到记录):去主库查对应 SQL 的 WHERE 条件,用相同条件在从库 INSERT 一行“占位”数据(字段可填 NULL 或默认值,只要主键/唯一键存在即可) -
1062(主键重复):在从库SET sql_log_bin = 0后DELETE冲突行,再START REPLICA - 真要跳:停复制 →
SET GLOBAL sql_replica_skip_counter = 1→START REPLICA;但必须确认Relay_Log_Pos对应的是完整事务组起点,否则可能只跳半个事务 -
CHANGE REPLICATION SOURCE TO SOURCE_LOG_POS = ...更精确,但需用mysqlbinlog解析出事务结束位置(end_log_pos),直接跳到下一个事务开头
为什么 --slave-skip-errors 不推荐线上长期开启?
它是启动参数,只能在 my.cnf 里配,重启生效,无法动态调整。设成 1062,1032 看似省事,但后果严重:
- 所有同类型错误都被静默跳过,包括本该报警的人为误操作 无法区分“偶发冲突”和“持续性数据漂移”,掩盖底层不一致问题
- 一旦开启,
SHOW REPLICA STATUS里的Last_SQL_Error就不再显示这些错误,监控告警失效 - MySQL 8.0+ 中该参数被标记为 deprecated,未来版本可能移除
真正需要的是自动化检测 + 人工确认机制,而不是靠参数兜底。跳过永远是最后手段,不是常规流程。











