pt-table-checksum迁移后不能直接运行,必须先确认binlog_format=row、从库复制正常且延迟≤1秒、各从库存在percona.checksums表、校验用户权限完备,否则diffs=0为假阳性;真一致性需登录每台从库查percona.checksums中this_crc与master_crc是否相等。

迁移前后不能直接跑 pt-table-checksum —— 它只在主库执行、结果必须查从库的 percona.checksums 表才能确认是否真一致,迁移环境几乎必然缺前提条件,90% 的 “Diffs = 0” 是假阳性。
迁移后首次校验前必须手动确认的 4 个状态
工具不会主动报错退出,但缺一不可,否则校验无效:
-
SHOW VARIABLES LIKE 'binlog_format'必须返回ROW;若为MIXED或STATEMENT,需先在主库执行SET GLOBAL binlog_format = 'ROW'并写入配置文件持久化 -
SHOW SLAVE STATUS\G中Slave_IO_Running和Slave_SQL_Running都得是Yes,且Seconds_Behind_Master ;迁移后常因 GTID 不一致或 relay log 残留导致 SQL_THREAD 停滞 - 每个从库上都要有
percona.checksums表(--create-replicate-table只在主库建,不会同步);手动执行:CREATE DATABASE IF NOT EXISTS percona;CREATE TABLE IF NOT EXISTS percona.checksums (...) - 校验用户(如
chkuser)在每个从库上都得有:GRANT SELECT, REPLICATION CLIENT ON *.* TO 'chkuser'@'%';GRANT INSERT, UPDATE, DELETE ON percona.checksums TO 'chkuser'@'%'
为什么不能信命令行末尾的 “Diffs = 0”
这个输出只表示主库没往 percona.checksums 写差异记录,完全不反映从库是否同步成功或比对是否完成:
- 从库
SQL_THREAD若被停掉,percona.checksums根本收不到任何记录,this_crc字段全为NULL,但命令仍显示Diffs = 0 - 从库开了
replicate_ignore_db = percona,checksum 记录被过滤,master_crc和this_crc永远无法比对 - 真正判断一致性的唯一依据是登录每个从库执行:
SELECT * FROM percona.checksums WHERE this_crc != master_crc OR is_bad = 1
迁移后最小安全启动命令(显式控制所有关键路径)
禁用所有自动推测逻辑,避免卡在 Waiting for replica mysql2 或静默跳过表:
- 必须加
--no-check-binlog-format:迁移后主库基本已是ROW,不加会直接退出 - 必须显式指定从库发现方式:
--recursion-method="dsn=D=percona,t=dsns",并在主库percona.dsns表里填死每个从库的host/port/user/password - 必须限定范围:
--databases=mydb,避免误扫系统库;大表加--chunk-size=1000减少锁表时间 - 必须加
--max-lag=1:从库延迟超 1 秒自动暂停,防止校验“追着延迟跑”
示例命令:
pt-table-checksum \ --host=master_ip \ --port=3306 \ --user=chkuser \ --password=xxx \ --databases=mydb \ --no-check-binlog-format \ --replicate=percona.checksums \ --recursion-method="dsn=D=percona,t=dsns" \ --chunk-size=1000 \ --max-lag=1
哪些表会被静默跳过?怎么提前发现
没有主键或唯一非空索引的表会被自动跳过,且不报错、返回码仍是 0,极易被忽略:
- 日志中出现
Cannot chunk table without a primary key or unique not null index就代表该表根本没校验 - 用这条 SQL 提前筛查:
SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema','mysql','performance_schema') AND TABLE_NAME NOT IN (SELECT TABLE_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE CONSTRAINT_NAME='PRIMARY' OR (CONSTRAINT_NAME!='PRIMARY' AND NON_UNIQUE=0)) GROUP BY TABLE_SCHEMA, TABLE_NAME -
TEXT/BLOB字段参与 CRC32 计算时可能被截断,建议加--ignore-columns排除
最易被忽略的点:checksum 结果不是看主库输出,而是每台从库上 percona.checksums 表里的 master_crc 和 this_crc 是否相等——迁移后环境往往连这张表都不存在,或权限没开全,或复制链路不通,但工具一声不吭。











