必须先执行SELECT @@gtid_mode, @@enforce_gtid_consistency;确认GTID模式是否启用,若返回ON则只能用SET GTID_NEXT+'BEGIN; COMMIT;'空事务跳过,且须严格满足STOP SLAVE、slave_parallel_workers=0、完整提交三条件。

必须先确认 GTID 模式已启用,再用 SET GTID_NEXT + 空事务精准跳过——任何跳过操作都不解决数据不一致,只让 SQL 线程继续跑。
怎么确认当前是 GTID 复制模式
跳过前不查 gtid_mode,90% 的失败都源于此。直接执行:
SELECT @@gtid_mode, @@enforce_gtid_consistency;
如果返回 ON,说明是 GTID 模式,SET GLOBAL sql_slave_skip_counter = 1 会直接报错:ERROR 1858 (HY000): sql_slave_skip_counter can not be set when the server is running with @@GLOBAL.GTID_MODE = ON。此时只能走 GTID_NEXT 方式。
如何准确提取卡住的 GTID 值
别靠 Last_SQL_Error 猜,也别去 performance_schema.replication_applier_status_by_coordinator 查——它反映的是 coordinator 视角,而 GTID 卡点常在 worker 线程。正确做法是:
- 执行
SHOW SLAVE STATUS\G,重点看Last_SQL_Error字段,里面通常带完整 GTID,例如:Worker 1 failed executing transaction 'e46c9961-5780-11ea-bf2f-000c128a8b6b:12345' - 交叉验证:运行
SELECT * FROM performance_schema.replication_applier_status_by_worker WHERE LAST_ERROR_NUMBER != 0;,确认出错 worker 对应的LAST_ERROR_MESSAGE和GTID是否一致 - 注意区分
Retrieved_Gtid_Set(已拉取但未执行)和Executed_Gtid_Set(已执行),差集里那个没被执行的 GTID 才是你真正要跳过的
跳过操作必须满足的三个硬性条件
漏掉任意一条,空事务就白提交,复制仍卡死或报 ERROR 1840 (HY000):
-
STOP SLAVE必须先执行,且不能只停 IO 线程——要用完整命令停全部线程 -
slave_parallel_workers必须为 0:SET GLOBAL slave_parallel_workers = 0;,改完立刻SELECT @@slave_parallel_workers;确认,否则多线程下GTID_NEXT可能被忽略 -
SET GTID_NEXT = 'xxx:nnn';后必须跟BEGIN; COMMIT;——这不是可选步骤,而是强制动作;只设GTID_NEXT不提交事务,MySQL 永远不会把该 GTID 记入Executed_Gtid_Set
跳过之后最关键的三件事
跳过只是绕开错误,不是修复问题。不验证就认为“好了”,等于埋雷:
- 检查主从关键表行数是否一致:
SELECT COUNT(*) FROM db.table;,尤其注意带WHERE的删改是否漏同步 - 观察
SHOW SLAVE STATUS\G中Seconds_Behind_Master是否持续下降、Exec_Master_Log_Pos是否推进,且与主库SHOW MASTER STATUS的Position差距不再扩大 - 在主库执行测试插入:
INSERT INTO test_sync VALUES (UNIX_TIMESTAMP(), 'verify');,立刻去从库查这条记录是否存在——这是最直接的端到端验证
真正麻烦的从来不是跳过那条报错语句,而是跳过之后发现 auto-increment 偏移错位、唯一索引残留脏数据、或 binlog_format 切换导致后续事件解析异常。这些细节不校验,跳过动作本身毫无意义。


















