mysql如何解决主从复制报错_mysql slave status错误排查

6次阅读

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

mysql如何解决主从复制报错_mysql slave status错误排查

看到 Seconds_Behind_Master: NULLSlave_SQL_Running: No 怎么办

这说明 SQL 线程已停,主从复制中断。不是网络抖动那种临时延迟,而是明确卡在某条语句上。常见现象是执行 SHOW SLAVE STATUSG 后,Seconds_Behind_MasterNULLSQL_Delay 为 0,但 Slave_SQL_RunningNo,同时 Relay_Log_Pos 停滞不动。

先别急着跳过错误或重做从库——90% 的情况,问题出在 relay log 里那条失败的语句本身,比如主库写了唯一键冲突、删了从库不存在的表、或者用了从库不支持的函数。

  • SHOW SLAVE STATUSG 查看 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_FileExec_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_SetExecuted_Gtid_Set 的差值里。如果两者不一致,且 Seconds_Behind_Master 持续增长,说明 SQL 线程没在消费已拉取的 GTID 事件。

GTID 模式下不能靠位置偏移判断进度,得比对集合。

  • 执行 SELECT * FROM performance_schema.replication_applier_status_by_coordinator; 查看 coordinator 是否异常(如 APPLIER_STATUS = ERROR
  • 对比 Retrieved_Gtid_SetExecuted_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 检查是否有大量 IntvarQuery 事件缺失(表明某些语句被过滤或跳过时未报错)

主从数据是否真正一致,从来不是靠 Slave_SQL_Running: Yes 判断的。它只代表线程活着,不代表数据没丢、没乱、没漏。每次跳过错误后,至少抽样三张核心业务表做行数和校验和比对。

text=ZqhQzanResources