pt-table-checksum显示“一致”却存在数据差异,根本原因在于它默认只在主库计算校验和,从库是否同步该结果取决于复制延迟、binlog格式(如statement下now()导致crc32不一致)及percona.checksums表是否被复制。

pt-table-checksum 能用,但必须理解它不校验从库延迟、不自动修复、默认跳过系统库——直接上手容易误判主从一致。
为什么 checksum 结果显示“一致”却仍有数据差异?
常见现象是 DIFFS 列全为 0,但人工比对发现某条记录实际不一致。根本原因在于:pt-table-checksum 默认只在主库计算校验和并写入 percona.checksums 表,从库是否同步到该表、是否执行了对应的 REPLACE INTO ... SELECT CRC32(...) 操作,完全依赖复制延迟和 binlog 格式。
- 如果从库延迟 > 校验任务执行时间,
checksums表在从库尚未更新,查出来的DIFFS就是旧值(甚至为 NULL) - 若主库用
STATEMENT格式且语句含NOW()、UUID()等非确定函数,从库计算出的 CRC32 值天然不同,但工具不会报错,只会记为DIFFS=1—— 可你没注意这一列 -
percona.checksums表本身不在复制白名单里(默认被忽略),需确认从库是否开启了replicate_do_table = percona.checksums或类似配置
如何让 pt-table-checksum 真正反映从库实时状态?
关键不是加参数跑得更快,而是强制它“等从库追上再比”。核心操作是结合 --replicate 和 --sync-to-master,并手动验证同步点:
- 务必指定
--replicate=percona.checksums(不能省略库名),确保校验结果写入该表并参与复制 - 加上
--sync-to-master,工具会先查从库SHOW SLAVE STATUS\G的Exec_Master_Log_Pos,等待主库 binlog 写入对应位置后再开始分块校验 - 运行后立刻在从库执行:
SELECT * FROM percona.checksums WHERE master_cnt != this_cnt OR master_crc != this_crc LIMIT 5;—— 不要只信 stdout 的 summary 行 - 若用 GTID,需额外加
--set-gtid-purged=OFF避免 SET @@GLOBAL.gtid_purged 报错
遇到 “Cannot chunk table because of locks or inconsistent data” 怎么办?
这不是磁盘满或权限问题,而是 pt-table-checksum 在尝试估算分块大小时,发现表无主键、有重复索引、或存在长时间未提交的事务,导致 EXPLAIN PARTITIONS 失败或采样行数异常。
- 优先检查:是否存在未提交事务?用
SELECT * FROM information_schema.INNODB_TRX\G确认 - 无主键表必须加
--chunk-index指定一个唯一、非空、高选择性的字段(如created_at+ 自增 ID 组合),否则工具拒绝分块 - 若表有大量
DELETE未清理的空洞,--chunk-size-limit=2.0(默认 4.0)可降低单次扫描压力,避免锁表过久 - 禁止在高峰期对大表(>50GB)直接运行;先用
--dry-run看预估 chunk 数量,再配合--chunk-time=0.1控制每块耗时
校验出差异后,别急着跑 pt-table-sync
pt-table-sync 是把双刃剑:它生成的 REPLACE 或 DELETE/INSERT 语句会直接写主库 binlog,从库照单全收——但如果主库此刻还有业务写入,极易引发主键冲突或覆盖新数据。
- 先用
pt-table-sync --print --sync-to-master打印 SQL,人工核对前 10 条是否符合预期(尤其关注时间字段、逻辑删除标记) - 绝对不要在主库执行
--execute;应连接从库,加--sync-to-master --run-on-slave,让修复动作只发生在从库本地 - 修复前务必备份从库对应表:
mysqldump -h slave_host db table > table_bak.sql;pt-table-sync不做事务回滚,出错即停 - 若差异来自主库误操作(如 DROP TABLE 后恢复),
pt-table-sync无法还原结构,此时应切流、重搭从库
真正卡住人的从来不是命令怎么敲,而是校验窗口期里主从复制的瞬时状态、binlog 格式隐含的不确定性、以及 percona.checksums 这张表本身是否真的被复制了——盯住这三点,比调任何参数都管用。











