必须先确认gtid模式:执行show variables like 'gtid_mode',on为gtid模式,off为传统模式;gtid模式下禁用sql_slave_skip_counter,应通过set gtid_next、begin;commit跳过事务;传统模式仅statement格式支持sql_slave_skip_counter,且需停sql线程并禁用多线程复制。

先确认是 GTID 还是传统复制模式
跳过事务前必须查清复制模式,否则命令直接报错或行为失控。执行 SHOW VARIABLES LIKE 'gtid_mode';,返回 ON 表示启用 GTID;返回 OFF 则为传统模式(Auto_Position=0)。别跳过这步——SET GLOBAL sql_slave_skip_counter = 1 在 GTID 模式下会触发 ERROR 1858 (HY000),而 GTID 模式下硬跳 sql_slave_skip_counter 会被 MySQL 8.0.23+ 标记为 deprecated,新环境应避免依赖。
GTID 模式下跳过单个错误事务(推荐)
GTID 跳过精准、可追溯,但步骤严格,漏一步就失败:
- 执行
STOP REPLICA;(MySQL 8.0.22+ 语法,旧版用STOP SLAVE;) - 从
SHOW SLAVE STATUS\G的Last_SQL_Error字段提取出错事务的完整 GTID,形如e46c9961-5780-11ea-bf2f-000c128a8b6b:12345,注意大小写、冒号、分号都不能错 - 按顺序执行三步:
SET GTID_NEXT = 'e46c9961-5780-11ea-bf2f-000c128a8b6b:12345';→BEGIN; COMMIT;→SET GTID_NEXT = 'AUTOMATIC'; - 执行
START REPLICA;
BEGIN; COMMIT; 不是摆设——它消耗掉该 GTID,防止复制线程重试原事务;若跳过此步,SQL 线程仍卡在相同错误上。
非 GTID 模式下跳过事务(仅限 STATEMENT 格式)
sql_slave_skip_counter 仅对基于语句的复制(binlog_format = STATEMENT)有效,且有硬性限制:
- 必须先停 SQL 线程:
STOP REPLICA SQL_THREAD;(不能只停 IO 线程) - 若启用了多线程复制(
slave_parallel_workers > 0),该变量行为不可靠,建议临时设为 0:SET GLOBAL slave_parallel_workers = 0; - 执行
SET GLOBAL sql_slave_skip_counter = 1;后再START REPLICA SQL_THREAD; - ROW 格式下该命令完全无效,会报
ERROR 1374 (HY000)
跳过之后,Exec_Master_Log_Pos 不会推进,它跳的是 relay log 中“下一个事务”,不是错误本身——如果错误事务包含多条语句,可能只跳过其中一部分,后续仍报错。
跳过之后必须验证的三件事
跳过只是让线程跑起来,不是修复数据不一致:
- 主从关键表执行
SELECT COUNT(*) FROM db.table;,行数必须一致;带WHERE的删改容易漏同步,需单独核对 - 观察
Seconds_Behind_Master是否持续下降、Exec_Master_Log_Pos是否推进,且与主库SHOW MASTER STATUS的Position差距不再扩大 - 在主库插入带时间戳的测试记录:
INSERT INTO test_sync VALUES (UNIX_TIMESTAMP(), 'verify');,立刻去从库查是否存在
真正麻烦的从来不是那条报错语句,而是跳过之后才发现:auto-increment 值偏移、唯一索引残留脏数据、或 NOW() 在 STATEMENT 模式下重放结果不同——这些不会立刻报错,但会在下次 INSERT 或 UPDATE 时突然爆发。











