先看last_sql_error,别急着start slave;看到slave_sql_running: no,第一反应是执行show slave status\g定位last_sql_error字段,明确错误码(如1062、1032、1418)及上下文,再结合mysqlbinlog解析relay log确认真实sql,区分跳过或手动修复。

先看Last_SQL_Error,别急着START SLAVE
看到 Slave_SQL_Running: No,第一反应不是重启复制,而是立刻执行 SHOW SLAVE STATUS\G,盯住 Last_SQL_Error 字段。它直接告诉你 SQL 线程卡在哪条语句、什么错误码——比如 Error_code: 1062(主键重复)、Error_code: 1032(找不到记录)、Error_code: 1418(函数不安全)等。这些错误成因完全不同:1062 常因从库残留了不该有的数据;1032 往往说明主从某行已不一致;1418 则和权限或 binlog_format 有关,跟数据一致性无关。
RBR模式下必须用mysqlbinlog解析relay log
MySQL 5.7+ 默认是 RBR(基于行的复制),Last_SQL_Error 通常只显示位置信息,例如 at master log mysql-bin.000012, end_log_pos 123456,看不到真实 SQL。这时必须用 mysqlbinlog 解析从库本地的 relay log:
mysqlbinlog --base64-output=decode-rows -v \ --start-position=123400 --stop-position=123500 \ /var/lib/mysql/relay-log.000001 > err.sql
重点看输出里 ### UPDATE 或 ### DELETE 前后的表名、WHERE 条件。注意:
- Docker 环境下,relay log 文件名可能带主机名前缀,先用
ls /var/lib/mysql/*relay*确认真实路径 - 如果解析出的语句在从库上手动执行也报错(如
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 下风险很高——它可能跳过一个事务里的部分行变更,留下半截脏数据。
跳过错误前必须确认 binlog_format 和业务容忍度
SET GLOBAL sql_slave_skip_counter = 1 是临时跳过当前事务的“止血针”,但有严格前提:
- 只对 SBR(基于语句的复制)可靠;RBR 下它可能跳过一个事务里的部分行变更,留下半截脏数据
- 仅适用于单次偶发错误,比如一条误删引发的
1032,且你确认主库该操作合理、从库缺失可接受 - 执行前必须
STOP SLAVE,执行后START SLAVE,否则无效 - 跳过后务必再查
Seconds_Behind_Master是否归零,并比对关键表数据 - 绝对禁止配置
slave_skip_errors = all:它会掩盖主键冲突、外键失败、DDL 执行失败等严重问题,等于主动关闭数据一致性监控
真正棘手的从来不是怎么跳过,而是如何确认那一行到底该不该存在——这需要结合业务日志、binlog 时间点、以及主从两侧的完整快照交叉验证,而不是只盯着 Last_SQL_Error 里的那行字。











