Last_SQL_Error字段真实有效当且仅当Slave_SQL_Running: No且Seconds_Behind_Master为NULL、Exec_Master_Log_Pos长期停滞;此时需结合mysqlbinlog解析Relay_Master_Log_File与Exec_Master_Log_Pos定位原始语句,而非依赖grep或忽略数据一致性。

怎么看Last_SQL_Error字段是否真实有效
很多同学一看到Last_SQL_Error里有报错就直接跳过,结果跳完发现又报新错——这说明错误没根除,只是被掩盖了。关键要确认这个错误是不是当前卡住 SQL 线程的“真凶”。Slave_SQL_Running: No时,Last_SQL_Error一定非空;但如果Seconds_Behind_Master是NULL且Exec_Master_Log_Pos长期不动,那它大概率就是源头。别信Relay_Log_Space在涨——那是日志还在写入,但 SQL 线程根本没消费。
常见干扰项:Last_IO_Error为空不代表 IO 没问题,它只记录网络/权限类失败;而Last_SQL_Error才是 SQL 线程执行失败的唯一出口。MySQL 默认不把这类错误写进error.log,所以翻日志不如直接查SHOW SLAVE STATUS\G。
怎么用Relay_Master_Log_File和Exec_Master_Log_Pos反查原始SQL
光看Last_SQL_Error往往不够,比如Error_code: 1062; Duplicate entry '123' for key 'PRIMARY',你得知道到底是哪条INSERT触发的、影响哪张表。这时候必须定位到 relay log 里的具体事件位置。
- 从
SHOW SLAVE STATUS\G中抄出Relay_Master_Log_File(例如localhost-bin.000094)和Exec_Master_Log_Pos(例如33622483) - 去从库上找 relay log 文件,路径通常在
relay_log变量指定目录下,文件名类似hostname-relay-bin.000002 - 用
mysqlbinlog解析:mysqlbinlog --base64-output=DECODE-ROWS -v --start-position=33622483 hostname-relay-bin.000002
- 重点看输出里
### INSERT INTO或### UPDATE开头的行,以及紧跟着的### WHERE条件——这才是实际执行失败的语句
注意:如果复制模式是 RBR(@@binlog_format = ROW),mysqlbinlog输出的是伪 SQL,不是原始语句,但WHERE部分仍能帮你锁定冲突行。
为什么直接grep relay log容易漏掉关键信息
有人习惯用grep -A 5 "Duplicate" hostname-relay-bin.000002,这基本无效。relay log 是二进制格式,直接 grep 只能匹配到乱码或极少数可读字符串,根本找不到结构化事件。必须用mysqlbinlog带--base64-output=DECODE-ROWS -v参数解析,否则看到的全是@1=... @2=...这种占位符,没法判断业务含义。
另一个坑是误用Read_Master_Log_Pos——它是 IO 线程拉到哪了,不是 SQL 线程执行到哪了。真正要盯的是Exec_Master_Log_Pos,它才对应 SQL 线程最后成功执行的位置。
遇到1032或1062错误时,跳过前必须人工核对主库状态
Error_code: 1032(Can't find record)和Error_code: 1062(Duplicate entry)本质都是主从数据不一致,跳过只是绕开,不是修复。
- 对
1062:先连主库查SELECT * FROM table_name WHERE id = X,确认这条记录是否存在;存在,说明从库多了一条,该删;不存在,说明主库刚插入,但从库已有旧数据,得查是否人为写入 - 对
1032:同样查主库,看那行是否已被删除;若已删,跳过安全;若主库仍有该行,说明从库误删,不能跳,得从备份恢复或用mysqlbinlog回放缺失变更 - 所有操作前必须
STOP SLAVE SQL_THREAD,避免边查边同步导致状态漂移
最容易被忽略的一点:没有主键的表在并行复制下极易触发1032,因为 MySQL 依赖隐式row_id定位行,而主从各自维护计数器。这种表即使跳过一次,下次照样崩——加显式主键才是根治方案。


















