跳过MySQL主从错误会导致行级数据不一致:UPDATE跳过使从库保留旧值,DELETE跳过致从库残留数据,INSERT跳过掩盖双写缺陷;pt-table-sync通过逐行比对生成反向SQL修复,但需谨慎执行并验证。

跳过 MySQL 主从错误后,数据不一致到底有多严重
跳过错误(比如用 SET GLOBAL sql_slave_skip_counter = 1 或 START SLAVE SKIP_COUNTER = 1)不是“继续同步”而是“主动丢弃一条变更”,主库写入了,从库没执行——这直接导致行级差异。尤其在 UPDATE/DELETE 场景下,一行在主库被改掉或删了,从库还留着旧值或残留行,后续基于该行的业务逻辑(比如订单状态流转、库存扣减)可能出错。
常见错误现象:Slave_SQL_Running: No 伴随 ERROR 1032 (HY000): Can't find record in 'xxx' 或 ERROR 1062 (23000): Duplicate entry 'xxx' for key 'PRIMARY';此时若盲目跳过,很可能已漏掉关键状态更新。
- UPDATE 语句跳过 → 从库该行仍是旧值,下游报表、风控规则全按错数据跑
- DELETE 语句跳过 → 从库多出一行,如果应用做“主键存在即校验通过”,会误判业务状态
- INSERT 语句跳过且主键冲突 → 可能掩盖上游双写或幂等缺陷,问题延后爆发
pt-table-sync 怎么定位并修复不一致
pt-table-sync 不是靠 binlog 回放补数据,而是逐行比对主从表内容,生成反向 SQL 让从库“对齐”主库。它默认只输出 SQL,不自动执行,必须加 --execute 才真正修复。
使用场景:主从结构稳定、网络延迟低、表有主键或唯一键(否则无法准确定位差异行)。
- 基本命令:
pt-table-sync --sync-to-master h=从库IP,u=用户,p=密码,D=库名,t=表名 --print先看要执行哪些 SQL - 必须加
--sync-to-master,否则默认以第一个实例为基准(容易搞反方向) - 大表慎用:
pt-table-sync会分块 SELECT 比对,但单次锁行+网络传输仍可能拖慢从库,建议避开业务高峰 - 遇到无主键表?它会退化为全表扫描比对,速度极慢且易超时,先补唯一索引再操作
为什么不能直接用 REPLACE INTO 或 INSERT ... ON DUPLICATE KEY UPDATE
这些语句看似能“覆盖”不一致,但它们只解决“写入冲突”,不解决“逻辑缺失”。比如主库某行被 DELETE,从库还存在——REPLACE INTO 无法感知该行该删,只会尝试插入(失败)或更新(无意义)。
更危险的是:如果从库那行其实是主库早先跳过的一次 INSERT,现在用 INSERT ... ON DUPLICATE KEY UPDATE 强制更新,等于把本该不存在的数据“复活”了,一致性反而更差。
-
REPLACE INTO是 DELETE + INSERT,会触发额外的自增 ID 分配和外键检查,可能扰乱主键连续性 -
INSERT ... ON DUPLICATE KEY UPDATE要求所有字段都参与 SET,漏写字段就会保留旧值,造成部分字段未同步 - 两者都无法处理“主库有、从库无”的 INSERT 缺失,或“主库无、从库有”的 DELETE 遗留
修复后必须验证的三个点
执行 pt-table-sync --execute 后,别急着关终端。不一致不是修完就消失,得确认它真被消除了,且没引入新问题。
- 立刻查
SHOW SLAVE STATUS\G,确认Seconds_Behind_Master归零、Slave_SQL_Running为 Yes - 用
pt-table-checksum对同一张表再跑一次校验(注意指定相同 chunk-size),确认 checksum 值主从一致 - 抽样验证业务关键字段:比如订单表查几个刚被 sync 的 order_id,对比主从的
status、updated_at是否完全一样
最容易被忽略的是:修复过程本身可能卡住复制线程(比如大事务阻塞了后续 relay log 执行),所以修完必须盯 5 分钟复制延迟曲线,而不是只看命令返回成功。


















