应先执行SHOW SLAVE STATUS\G查看Last_SQL_Error字段定位错误码(如1062、1032、1418),再结合mysqlbinlog解析relay log确认真实SQL;1062和1032须优先手动修复数据,跳过仅限SBR且单次偶发,严禁slave_skip_errors=all。

直接看 Last_SQL_Error 字段定位错误码
看到 Slave_SQL_Running: No,第一件事不是 START SLAVE,而是执行 SHOW SLAVE STATUS\G,盯住 Last_SQL_Error 字段。它明确告诉你卡在哪条语句、什么错误码——比如 Error_code: 1062(主键重复)、Error_code: 1032(找不到记录)、Error_code: 1418(函数不安全)。
这些错误成因完全不同:
-
1062多半是从库已有同主键数据(比如手动 INSERT 过),不是主库写错了 -
1032表示从库执行UPDATE/DELETE时 WHERE 条件查不到行,可能主库删了但从库没同步上,也可能表没主键导致行定位漂移 -
1418或1236通常和binlog_format、函数定义、权限有关,跟数据一致性无关,要单独处理
RBR 模式下必须用 mysqlbinlog 解析 relay log
MySQL 5.7+ 默认是 RBR(基于行的复制),Last_SQL_Error 往往只显示位置信息,例如 at master log mysql-bin.000012, end_log_pos 123456,看不到真实 SQL。这时必须解析从库本地的 relay log:
- 先用
ls /var/lib/mysql/*relay*确认 relay log 文件名(Docker 环境下可能带 host 前缀) - 执行:
mysqlbinlog --base64-output=decode-rows -v --start-position=123400 --stop-position=123500 /var/lib/mysql/relay-log.000001 > err.sql - 重点看输出里
### UPDATE或### DELETE前后的表名、WHERE 条件,别只信报错信息——实际执行的可能是被改写过的语句 - 如果解析出的语句在从库手动执行也报错(如
Table 'xxx' doesn't exist),说明 DDL 没同步或顺序错乱 - 如果语句本身没问题,但从库查不到对应行,就得分别查主从两边该行是否存在——不能默认主库是对的
1062 和 1032 错误优先手动修复,不是跳过
这两类错误本质是主从数据不一致,跳过只是绕开症状,不是修复:
- 对
1062:先SELECT * FROM table WHERE id = X查从库是否有冲突行;有则DELETE掉,再START SLAVE - 对
1032:查主库 binlog 或业务日志,确认那行是否真被删了;若主库已删,从库补删即可;若主库没删,说明从库误删,得从备份恢复或回放缺失 binlog -
SET GLOBAL sql_slave_skip_counter = 1在 RBR 下风险很高——它可能跳过一个事务里的部分行变更,留下半截脏数据 - 跳过仅限 SBR(
SELECT @@binlog_format返回STATEMENT)且单次偶发;GTID 模式下完全无效,必须用SET GTID_NEXT+ 空事务
跳过前必须确认 skip 的是“哪一层”的错误
盲目配置 slave_skip_errors = all 是生产环境大忌:
- 它会掩盖
1062(主键冲突)、1213(锁超时)、1050(表已存在)等严重问题,等于主动关闭数据一致性监控 - 真正可控的跳过方式只有两种:
sql_slave_skip_counter(SBR 下临时跳过当前事务)或slave-skip-errors=1062,1032(配置级白名单,仍需人工核对) - 无论哪种跳过,执行后必须立刻检查
Seconds_Behind_Master是否归零,并比对关键表的COUNT(*)和主键范围 - 最常被忽略的是:跳过之后,
Relay_Log_Space可能持续增长但Exec_Master_Log_Pos不动——说明 relay log 在写,SQL 线程根本没消费,问题还在


















