先看last_sql_error字段,它直接显示错误码(如1062、1032)和报错语句片段;rbr模式下需用mysqlbinlog解析relay log定位真实sql;1062和1032须先确认数据状态再修复,不可盲目跳过。

直接看Last_SQL_Error字段,别翻error.log
MySQL主从同步卡住时,Last_SQL_Error是第一手线索,比错误日志更准、更实时。执行SHOW SLAVE STATUS\G后,立刻盯住这个字段——它会明确写出错误码(如Error_code: 1062)和报错语句片段(比如Duplicate entry '123' for key 'PRIMARY')。错误日志(error.log)默认不记录这类SQL执行失败细节,除非你开了log_error_verbosity = 3(MySQL 8.0.22+),否则grep Got fatal error或relay-log往往只能看到IO层问题,不是SQL线程卡点。
RBR模式下Last_SQL_Error不显示完整SQL?用mysqlbinlog解析relay log
RBR(基于行的复制)是MySQL 5.7+默认模式,Last_SQL_Error通常只提示位置(如at master log mysql-bin.000012, end_log_pos 123456),看不到原始语句。必须靠mysqlbinlog反查:
- 从
SHOW SLAVE STATUS\G里抄出Relay_Master_Log_File(如localhost-bin.000094)和Exec_Master_Log_Pos(如33622483) - 在从库上找到对应relay log文件:
ls /var/lib/mysql/*relay*(Docker环境注意文件名可能带主机名前缀) - 执行:
mysqlbinlog --base64-output=DECODE-ROWS -v --start-position=33622483 hostname-relay-bin.000002 - 重点看输出中以
### UPDATE、### DELETE或### INSERT开头的块,以及紧随其后的### WHERE条件——这才是真实触发错误的行变更逻辑
看到Error_code: 1062或1032就跳过?先确认数据状态
错误码是修复入口,不是跳过指令:
-
Error_code: 1062(主键重复):先SELECT * FROM table WHERE id = X查从库是否真有冲突行;有则删掉,再START SLAVE;别直接SET GLOBAL sql_slave_skip_counter = 1,RBR下它可能跳过事务内部分行,留脏数据 -
Error_code: 1032(找不到记录):查主库binlog确认那行是否已被删;若主库已删,从库补删即可;若主库没删,说明从库误删,得回放缺失binlog或从备份恢复 -
Error_code: 1418或1236:和数据一致性无关,通常是函数创建不安全或binlog格式不匹配,需单独调binlog_format或加--log-bin-trust-function-creators
SHOW FULL PROCESSLIST里找正在卡住的SQL
如果SQL线程还在运行但明显卡住(Seconds_Behind_Master持续增大),Last_SQL_Error为空或旧错误,就得看实时执行状态:
- 执行
SHOW FULL PROCESSLIST(必须加FULL,否则Info字段被截断) - 只关注
User = 'system user'且Command = 'Connect'的那行 - 看
State字段,比如Waiting for table metadata lock,再看Info列——这里就是当前卡住的真实SQL,如UPDATE orders SET status = 'shipped' WHERE id = 123456789
真正卡住的SQL往往不在Last_SQL_Error里,因为它还没执行完就锁住了;这时候SHOW FULL PROCESSLIST比任何日志都直接。











