1032报错需定位主库binlog中出错事务的精确坐标,通过show slave status获取master_log_file和read_master_log_pos,用mysqlbinlog解析对应位置找到缺失记录的where条件,验证主库存在后导出补入从库并跳过错误,最终加主键根治。

直接定位1032报错对应的binlog位置和操作条件
只看Last_Error里那句Can't find record in 't'毫无用处,关键要拿到出错事务在主库binlog中的精确坐标。从SHOW SLAVE STATUS\G中提取Master_Log_File和Read_Master_Log_Pos(注意不是Exec_Master_Log_Pos),例如:mysql-bin.000013 和 440267874。
然后在主库执行:
mysqlbinlog --no-defaults -v -v --base64-output=DECODE-ROWS /var/lib/mysql/mysql-bin.000013 | grep -A 20 "end_log_pos 440267874"
输出里找类似### DELETE FROM `db`.`t` WHERE @1=12345 AND @2='xxx'这样的行——这就是从库缺失的那条记录的完整定位条件。
- 如果grep没结果,说明该position不在当前binlog文件末尾附近,尝试扩大-A范围或检查是否被rotate
- 确保主库binlog路径正确,
/var/lib/mysql/只是常见路径,需根据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 --where="id=12345" db t > missing_row.sql
传到从库执行前,必须加SET SQL_LOG_BIN = 0;(GTID模式下强制要求,否则INSERT又被同步回去,造成死循环)。
- 导出时加
--skip-triggers避免触发器干扰 - 若表有TEXT/JSON字段,注意
mysqldump默认不转义换行符,导入后可能肉眼难辨差异 - 不要用
INSERT ... SELECT从主库直插从库,网络中断会导致半截数据
推进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精度(微秒)、ENUM隐式转换、JSON格式空格、TEXT末尾不可见字符 - 若用脚本比对,建议用
HEX()包裹字段,避免编码或隐式类型转换干扰 - 发现任意字段值不同,说明后续UPDATE大概率再次触发1032
根治:给无主键表加主键或唯一键
反复出现1032,90%以上是因为表没有PRIMARY KEY或UNIQUE KEY。RBR复制依赖索引快速定位,没主键就全表扫描,稍有字段值差异就失败。
检查方法:
SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_SCHEMA = 'db' AND TABLE_NAME = 't';
为空即无主键。加主键示例:
ALTER TABLE db.t ADD COLUMN id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY FIRST;
注意字段类型要兼容现有数据(比如不能用NOT NULL加到含NULL值的列上)。
- 加主键前先
ANALYZE TABLE t;更新统计信息,避免DDL期间锁表过久 - 若表极大,考虑用
pt-online-schema-change在线添加 - 加完立刻关掉并行复制测试:
SET GLOBAL slave_parallel_workers = 0;,确认稳定后再逐步调高
最容易被忽略的是:补完数据、跳过错误、甚至加了主键,都掩盖不了一个事实——只要曾经用过SET sql_log_bin = 0批量导入,从库就可能缺更多行,必须用pt-table-checksum做全量校验,而不是只盯住当前报错这一行。











