sql线程已停导致主从复制中断,需先查last_sql_error定位错误,再结合mysqlbinlog分析binlog确认语句可重放性,避免盲目跳过;gtid模式下须用gtid_next跳过且比对retrieved/executed gtid集合;跳过仅恢复线程运行,不代表数据一致,须校验表结构与数据。

看到 Seconds_Behind_Master: NULL 或 Slave_SQL_Running: No 怎么办
这说明 SQL 线程已停,主从复制中断。不是网络抖动那种临时延迟,而是明确卡在某条语句上。常见现象是执行 SHOW SLAVE STATUS\G 后,Seconds_Behind_Master 为 NULL,SQL_Delay 为 0,但 Slave_SQL_Running 是 No,同时 Relay_Log_Pos 停滞不动。
先别急着跳过错误或重做从库——90% 的情况,问题出在 relay log 里那条失败的语句本身,比如主库写了唯一键冲突、删了从库不存在的表、或者用了从库不支持的函数。
- 用
SHOW SLAVE STATUS\G查看Last_SQL_Error字段,它直接告诉你哪条语句、哪个库、哪个表、什么错误码(如ERROR 1062) - 用
mysqlbinlog --base64-output=decode-rows -v解析Relay_Master_Log_File+Exec_Master_Log_Pos对应的主库 binlog 片段,确认原始语句是否真的不可重放 - 如果错误是「从库有数据,主库没删干净」导致的唯一键冲突,不要盲目
SET GLOBAL sql_slave_skip_counter = 1;先查SELECT * FROM table WHERE ...确认两边数据实际差异
STOP SLAVE; START SLAVE; 为什么有时无效
因为 START SLAVE 只是重启 IO 和 SQL 线程,不会自动修复已损坏的 relay log 或跳过卡住的位置。如果 SQL 线程在重放某条语句时报错并退出,再 START SLAVE 还会从同一个位置重试,陷入死循环。
真正起作用的是调整 SQL 线程的执行起点,而不是启停本身。
- 确认当前卡点:
Relay_Master_Log_File和Exec_Master_Log_Pos是关键坐标 - 若确定要跳过当前错误语句:用
SET GLOBAL sql_slave_skip_counter = 1,然后START SLAVE——注意这个变量只对下一条语句生效,且仅在binlog_format = STATEMENT下可靠 - 更稳妥的方式是用
CHANGE MASTER TO ... MASTER_LOG_FILE='xxx', MASTER_LOG_POS=yyy手动指定下一个应读取的 binlog 位置(需提前在主库查好该位置之后的合法事件) -
sql_slave_skip_counter在 GTID 模式下完全失效,必须用SET GTID_NEXT+ 空事务方式跳过
GTID 复制下 Slave_SQL_Running_State 显示 Waiting for gtid event from coordinator 却不推进
这不是卡住,是正常状态。真正的问题藏在 Retrieved_Gtid_Set 和 Executed_Gtid_Set 的差值里。如果两者不一致,且 Seconds_Behind_Master 持续增长,说明 SQL 线程没在消费已拉取的 GTID 事件。
GTID 模式下不能靠位置偏移判断进度,得比对集合。
- 执行
SELECT * FROM performance_schema.replication_applier_status_by_coordinator;查看 coordinator 是否异常(如APPLIER_STATUS = ERROR) - 对比
Retrieved_Gtid_Set和Executed_Gtid_Set:用SELECT GTID_SUBTRACT('a-b-c', 'a-b-d')算出差集,看哪些 GTID 还没执行 - 如果差集里有明显不该出现的 GTID(比如来自其他分支或已删除的主库),可能是主库被误切、或从库之前执行过手动写入,破坏了 GTID 一致性
- 修复前务必确认主库 binlog 还在:
SHOW BINARY LOGS;查对应Retrieved_Gtid_Set中最大 GTID 所在文件是否仍存在
跳过错误后 SHOW SLAVE STATUS 显示正常,但业务数据还是不一致
跳过只是让 SQL 线程跑起来,不代表数据追平。特别是跳过 DDL(如 DROP TABLE)或跨库操作后,后续依赖该结构的 DML 会静默失败或写到错地方,而 Slave_SQL_Running 仍显示 Yes。
最危险的是“看起来好了,其实漏了一整张表”。
- 检查
Replicate_Do_DB/Replicate_Ignore_DB等过滤规则是否意外屏蔽了本该同步的库 - 用
pt-table-checksum对比主从表级数据一致性(注意避开业务高峰,且从库不能有写入) - 如果曾跳过 DDL,立刻检查从库对应表是否存在、字段类型是否一致、索引是否完整——
SHOW CREATE TABLE逐个比对 - 开启
log_slave_updates并定期抓取从库的 binlog,用mysqlbinlog检查是否有大量Intvar、Query事件缺失(表明某些语句被过滤或跳过时未报错)
主从数据是否真正一致,从来不是靠 Slave_SQL_Running: Yes 判断的。它只代表线程活着,不代表数据没丢、没乱、没漏。每次跳过错误后,至少抽样三张核心业务表做行数和校验和比对。










