mysql主从不一致是复制链路失效的必然结果,需先分类识别:1032错误源于rbr回放时找不到行,多因无主键+并行复制;pt-table-sync可能误删从库合法数据;max_allowed_packet不一致导致静默截断;sql_mode、时区、statement模式等引发隐性不一致。

MySQL主从数据不一致不是“偶发故障”,而是复制链路中某个环节被绕过、失效或执行偏差的必然结果。自动修复只是手段,关键在于先识别出是哪一类不一致——有些能跳过,有些必须重拉,有些根本不能自动修。
Slave_SQL_Running: No 且报错 Error_code: 1032 怎么快速定位和处理
这是最典型的“行找不到”错误,本质是 RBR(基于行的复制)在从库回放时,用主键/唯一索引去定位目标行失败了。常见于没主键的表 + 并行复制开启后。
-
SHOW SLAVE STATUS\G中确认Slave_SQL_Running: No,Last_SQL_Error含Error_code: 1032和Can't find record in 'xxx' - 立刻查该表:
SHOW CREATE TABLE tb_inventory_log,看有没有PRIMARY KEY或UNIQUE KEY - 如果没主键,不要直接
SET GLOBAL sql_slave_skip_counter = 1—— 跳过一次,下次还报,且数据已错位 - 紧急恢复可临时关并行复制:
STOP SLAVE; SET GLOBAL slave_parallel_workers = 0; START SLAVE;,再观察是否稳定 - 根治必须加主键:
ALTER TABLE tb_inventory_log ADD id BIGINT AUTO_INCREMENT PRIMARY KEY FIRST(注意字段类型要兼容现有数据)
从库被写入导致不一致,为什么 pt-table-sync 有时会越修越错
pt-table-sync 默认假设“主库是真理源”,它会把从库多出的数据删掉、缺失的数据补上。但如果从库真被人工 INSERT 过,而这条数据在业务逻辑里本该存在(比如双写架构下未收敛),直接同步就会丢数据。
- 运行前先做一致性快照:
pt-table-checksum --no-check-binlog-format --replicate=test.checksums h=master_host,u=repl,p=xxx - 检查
test.checksums表,确认哪些表chunk的diff不为 0,再人工比对几条差异记录 - 若发现从库有主库没有的合法数据,必须先停掉应用写入,再决定是反向同步(
--sync-to-master)还是人工 merge -
pt-table-sync执行时加--print参数预览 SQL,千万别裸跑--execute - 特别注意外键约束表:
pt-table-sync不自动处理级联,可能触发ERROR 1452
max_allowed_packet 不一致导致的静默不一致怎么发现
这类问题不会报错中断,但会导致大事务在从库被截断或执行失败,SQL线程却仍显示 Yes,Seconds_Behind_Master 也不涨——最危险的“假正常”。
- 主库执行一个超大
INSERT ... SELECT,然后立刻查从库对应表行数:SELECT COUNT(*) FROM huge_table - 对比主从
SHOW VARIABLES LIKE 'max_allowed_packet',必须严格相等(建议统一设为 64M) - 检查从库错误日志:
grep -i "packet" /var/log/mysql/error.log,留意Got a packet bigger than 'max_allowed_packet' bytes - 修改后必须重启 MySQL(不是
SET GLOBAL就生效),因为该变量是只读启动参数 - 上线前用
mysqlbinlog --base64-output=decode-rows -v binlog.000001 | grep -A5 -B5 "big_insert"模拟回放,验证是否截断
真正难修的从来不是报错,而是没报错的不一致——比如 sql_mode 不同导致字符串自动截断、TIMESTAMP 字段因时区不同存了不同值、或者 binlog_format=STATEMENT 下 NOW() 函数在主从生成不同时间戳。这些没法靠工具一键修复,得靠定期 checksum + 业务层校验兜底。











