pt-table-checksum显示不一致但数据实际相同,主因是group_concat默认截断(group_concat_max_len=1024),导致拼接结果不同而md5校验失败;需调大该值、显式处理null、确保order by字段有索引且排序确定。

pt-table-checksum执行后显示不一致,但实际数据相同
这是最常被误判的情况:校验工具报告 chunk 不一致,但人工抽样比对字段值完全一样。根本原因通常是 GROUP_CONCAT 静默截断——MySQL 默认 group_concat_max_len = 1024,拼接长文本、JSON 或多字段时直接砍掉尾部,导致两端 MD5 值必然不同。
实操建议:
- 迁移前在源库和目标库都执行:
SET SESSION group_concat_max_len = 1000000 - 若用
mysqldump --tab导出做离线校验,还需检查客户端连接参数(如 MySQL CLI 的--default-group-concat-max-len) - 校验语句中避免裸写
GROUP_CONCAT(col),改用GROUP_CONCAT(IFNULL(CAST(col AS CHAR), 'NULL'))显式处理 NULL 和类型
pt-table-checksum报错“Cannot find any tables”或跳过表
工具找不到表,往往不是路径或权限问题,而是表名大小写或数据库名含特殊字符没被正确解析。MySQL 在 Linux 下默认区分表名大小写(lower_case_table_names = 0),而 pt-table-checksum 内部使用 Perl 正则匹配,若表名含连字符、下划线或大写字母,可能被忽略。
实操建议:
- 用
SHOW TABLES FROM `db_name`确认实际表名,避免反引号遗漏 - 显式指定要校验的表:
pt-table-checksum --databases=db_name --tables=tbl_a,tbl_b ... - 若库名含短横线(如
my-app),必须加反引号:--databases=`my-app` - 检查
information_schema.tables中table_schema字段是否与命令中写的完全一致(包括末尾空格)
校验结果里“chunk”差异行数为 0,但 checksum 值不同
这说明分块逻辑本身没问题,但同一 chunk 内数据排序不一致,导致 GROUP_CONCAT(... ORDER BY ...) 拼出的字符串顺序不同。InnoDB 不保证无 ORDER BY 查询的返回顺序,尤其跨版本(5.7→8.0)、跨引擎或索引结构微调后更明显。
实操建议:
- 校验 SQL 中的
ORDER BY必须基于联合唯一键,例如ORDER BY id, created_at, updated_at,不能只写id - 确认排序字段上有有效索引,避免触发 filesort(可通过
EXPLAIN验证) - 禁用查询缓存和 optimizer_switch 中影响排序的选项(如
derived_merge=off),保持执行计划稳定 - 小表可绕过分块,用全表
SELECT MD5(CONCAT_WS('#', ...)) FROM tbl ORDER BY pk直接比对
pt-table-checksum在GTID模式下校验失败或延迟飙升
GTID 模式本身不干扰校验逻辑,但容易忽略两个关键点:一是从库未真正追平(Executed_Gtid_Set 虽相等,但可能跳过事务);二是 checksum 表写入被复制过滤规则拦截(如 replicate_ignore_db = percona)。
实操建议:
- 校验前先确认从库已执行完所有主库 GTID:
SELECT WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS('source_uuid:1-1000'); - 检查从库的
replicate_do_db/replicate_ignore_db是否屏蔽了percona库 - 确保 checksum 表建在从库上(不是只在主库建),且从库能写入该库(
read_only=OFF临时放开) - 避免在主库执行
pt-table-checksum同时做 DDL,GTID 模式下 DDL 会生成新事务,导致位点漂移
percona.checksums 表里的 this_crc 和 master_crc 具体值——差异是系统性(所有 chunk 都差)还是随机性(个别 chunk 差),决定了该调参数还是该查数据逻辑。











