必须补数据,不能只跳过:1032错误源于从库执行UPDATE/DELETE时目标行缺失,需通过SHOW SLAVE STATUS获取Master_Log_File和Read_Master_Log_Pos,用mysqlbinlog解析定位WHERE条件(如@1=12345),主库验证存在后导出该行并SET SQL_LOG_BIN=0导入从库,再SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1推进同步。

必须补数据,不能只跳过。1032错误不是日志解析失败,而是从库执行UPDATE或DELETE时目标行确实不存在——跳过能恢复同步,但下一次同条件操作仍会卡住。
定位binlog中出错事务的精确位置
光看Last_Error: Can't find record in 't'没用。真正要抓的是SHOW SLAVE STATUS\G输出里的两个字段:
-
Master_Log_File(如mysql-bin.000013) -
Read_Master_Log_Pos(注意不是Exec_Master_Log_Pos)
这两个值共同锁定了出错事务在主库binlog中的坐标。然后在主库执行:
mysqlbinlog --no-defaults -v -v --base64-output=DECODE-ROWS /var/lib/mysql/<code>mysql-bin.000013</code> | grep -A 20 "end_log_pos <code>440267874</code>"
输出里找类似### DELETE FROM `db`.`t` WHERE @1=12345 AND @2='xxx'这样的行——这就是缺失记录的完整定位条件。若grep无结果,可能是:
-
-A 20范围太小,尝试扩大到-A 50 - binlog已被rotate,需结合
SHOW VARIABLES LIKE 'datadir'确认真实路径 - 启用了
binlog_rows_query_log_events=ON,可直接看到原始SQL,但仍需核对WHERE条件是否匹配实际字段顺序
验证并导出缺失行到从库
拿到@1=12345这类条件后,先在主库验证是否存在:
SELECT * FROM db.t WHERE id = 12345;
存在才继续;不存在说明主库也丢了,得回溯业务操作。确认存在后导出:
mysqldump --no-create-info --skip-triggers --where="id=12345" db t > missing_row.sql
传到从库执行前,必须加SET SQL_LOG_BIN = 0;(GTID模式下强制要求,否则INSERT会被同步回主库,引发死循环)。导入命令为:
mysql db < missing_row.sql
注意:
- 别用
INSERT ... SELECT直插,网络中断会导致半截数据 - 表有
TEXT/JSON字段时,mysqldump默认不转义换行符,导入后可能肉眼难辨差异 - 若表长期无主键,
@1~@N对应整行所有字段,WHERE条件极长,且易因JSON空格、datetime毫秒等微小差异导致匹配失败
推进SQL线程并验证整行一致性
补完数据≠复制自动恢复。SQL thread仍卡在原地,必须手动推进:
STOP SLAVE;<br>SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;<br>START SLAVE;
检查Slave_SQL_Running: Yes且Seconds_Behind_Master开始下降才算成功。但更关键的是验证:
- 在主从库分别执行
SELECT * FROM db.t WHERE id = 12345;,逐字段比对(尤其DATETIME精度、JSON格式、ENUM默认值) - 若仍报1032,说明还有别的行缺失——不是单点问题,得用
pt-table-checksum全量校验 - 别忽略
sql_log_bin=0的历史导入:这类缺失往往集中在某几张表,补完后建议查主库binlog或操作日志确认是否批量漏同步
最容易被忽略的一点:补完只验证主键存在远远不够,字段值微小差异(比如JSON末尾多一个空格、DATETIME(3)和DATETIME(6))会导致后续UPDATE再次触发1032。


















