pt-table-checksum不报错≠主从数据一致,因其默认仅在主库计算checksum并写入percona.checksums表,是否同步到从库、是否被正确执行及比对需手动确认;输出“0 differences”仅表示主库校验无误,不代表主从数据一致。

pt-table-checksum 不报错 ≠ 主从数据一致,它默认只在主库算 checksum 并写入 percona.checksums 表,是否同步到备库、是否被正确执行、是否被比对,全靠你手动确认。
为什么 pt-table-checksum 执行完显示 “0 differences” 却还是不一致?
这是最常踩的坑:工具输出的 DIFFS 列为 0,仅表示“主库校验过程没出错”,不代表从库数据和主库一样。根本原因在于:
-
pt-table-checksum默认不连接从库查结果,只是把校验 SQL 发到 binlog,靠复制机制把percona.checksums表的记录同步过去 - 如果从库延迟高、SQL 线程停过、或配置了
replicate_ignore_db = percona,那percona.checksums根本不会出现在从库 - 即使表同步过去了,
master_crc(主库算的)和this_crc(从库自己算的)也可能因NOW()、UUID()、USER()等非确定性函数导致 CRC32 不等 —— 尤其在STATEMENT格式下
必须手动登录从库查 percona.checksums 表才能确认
校验完成后,别信工具输出,直接连从库执行:
SELECT db, tbl, this_crc, master_crc, this_cnt, master_cnt FROM percona.checksums WHERE this_crc != master_crc OR this_cnt != master_cnt OR is_bad = 1;
只要返回任意一行,就说明对应表存在不一致。注意:
-
this_crc是从库本地计算的校验值,master_crc是主库发来的值,二者不等才真有问题 - 如果查询返回空,但你怀疑有漏,再加条件
AND (master_crc IS NULL OR this_crc IS NULL),排查是否 checksum 记录根本没同步过来 - 确保从库上
percona.checksums表存在且可读:SHOW CREATE TABLE percona.checksums;
--replicate-check-only 要配 --recursion-method 才能真正连从库比对
想让 pt-table-checksum 主动连接从库并现场比对?光加 --replicate-check-only 不够,它默认仍只查主库的 percona.checksums。必须显式指定从库发现方式:
- 用
--recursion-method=dsn,并在percona.dsns表里填好从库连接信息(host/user/pass/port) - 或者用
--recursion-method=processlist(依赖主库SHOW PROCESSLIST中的从库连接),但要求主库能看见从库的复制线程连接 - 若从库只开放只读账号,需确保该账号有
SELECT权限(查percona.checksums),某些模式下还需INSERT/UPDATE(如重写 checksum)
大表校验卡住、锁表、拖慢业务时怎么调?
分块逻辑本身是保护机制,但参数不合理反而会放大影响:
- 默认按主键分片,若表无主键/唯一索引,工具会退化为全表扫描 +
LOCK IN SHARE MODE,极易阻塞写入 —— 务必提前确认SHOW CREATE TABLE - 用
--chunk-size控制单次处理行数(如--chunk-size=1000),避免单块过大;配合--chunk-size-limit=2.0防止自动扩得太猛 - 通过
--max-load="Threads_running=10"和--max-lag=5让工具感知负载和延迟,自动暂停,别硬扛 - 避开高峰期执行,且不要在从库开启
log_slave_updates=OFF—— 否则percona.checksums表无法被下游继续复制
真正容易被忽略的是:checksum 结果的生命周期。percona.checksums 表不会自动清理,旧记录堆积可能掩盖新问题;每次校验前最好先 truncate 或加 --where "ts > NOW() - INTERVAL 1 HOUR" 过滤,否则你比对的可能是三天前那次失败的残留结果。











