修复mysql主从1032错误需先从show slave status获取master_log_file和read_master_log_pos,用mysqlbinlog解析对应位置找出缺失记录的where条件,再在主库验证存在后导出并set sql_log_bin=0导入从库。

定位1032错误对应的binlog精确位置
只看Last_Error里那句Can't find record in 't'没用,关键要拿到出错事务在主库binlog中的坐标。从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/mysql-bin.000013 | grep -A 20 "end_log_pos 440267874"
输出中找类似### DELETE FROM `db`.`t` WHERE @1=12345 AND @2='xxx'这样的行——这就是从库缺失记录的完整WHERE条件。若grep无结果,可能position不在当前binlog末尾附近,需扩大-A范围或确认binlog是否已被rotate;路径/var/lib/mysql/只是常见值,应先查SHOW VARIABLES LIKE 'datadir'确认真实路径。
验证并补全缺失的那行数据
拿到@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 。不要用<code>INSERT ... SELECT直插,网络中断会导致半截数据。
推进SQL线程并比对整行一致性
补完数据不等于复制自动恢复,SQL thread仍卡在原地。必须手动推进:
STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; START SLAVE;
检查Slave_SQL_Running: Yes且Seconds_Behind_Master开始下降才算成功。但仅验证主键存在远远不够——字段值差异(比如DATETIME(6)精度、JSON格式空格、TEXT末尾换行、ENUM隐式转换)会导致后续UPDATE再次触发1032。务必在主从库分别执行:
SELECT * FROM db.t WHERE id = 12345;
逐字段肉眼或脚本比对。特别注意时间类型、枚举值、JSON字段、ENUM默认值行为差异。
根治:给表加主键或唯一键
1032反复出现,大概率是表长期无主键。RBR复制依赖主键或唯一键定位目标行;没有的话MySQL会退化为全表扫描匹配所有字段,稍有差异就报错,且并发复制(MTS)时更容易出问题。
立即执行:
ALTER TABLE t ADD COLUMN id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY FIRST;
如果无法加自增主键,至少补一个UNIQUE KEY覆盖常用查询条件。别依赖slave-skip-errors = 1032或频繁跳过,那是把数据不一致常态化。真正容易被忽略的是:即使主从COUNT(*)和MD5(HEX())都一致,单个字段的隐式类型转换或存储格式差异,也可能让下一次UPDATE立刻再报1032。











