mysql数据库迁移时如何检查数据完整性_mysql数据完整性验证

1次阅读

最直接的表级验证是比对源库和目标库的 checksum table 校验和,适用于千万行以内表;需辅以 count(*)、min/max 范围校验及手动抽样比对字段值,防范字符集、时区、精度等隐式差异。

mysql数据库迁移时如何检查数据完整性_mysql数据完整性验证

CHECKSUM TABLE 快速比对表级校验和

迁移后最直接的验证方式是比对源库和目标库同一张表的校验和。mysql 内置的 CHECKSUM TABLE 命令能生成整表数据的 CRC32 校验值,适合中小规模表(单表千万行以内)。注意它默认只校验数据行,不包含索引、AUTO_INCREMENT 值或表结构差异。

  • 在源库执行:CHECKSUM TABLE `db_name`.`table_name`;
  • 在目标库执行相同命令,对比返回的 Checksum 数值是否一致
  • 若表含浮点字段(Float/double),因精度表现可能跨版本/平台不一致,结果可能误报不同——此时应改用逻辑校验
  • 该命令会加读锁,大表执行期间影响线上查询,建议在低峰期操作或先在从库验证

select COUNT(*)SELECT MIN/MAX 验证基础行数与关键范围

这是零成本、无锁、最常被忽略的第一步。很多迁移失败其实连行数都不对,但大家直接跳进复杂校验。

  • 必须比对:源库和目标库的 COUNT(*),尤其注意 WHERE 条件是否被意外过滤(例如 mysqldump 默认跳过 INformatION_SCHEMA 或临时表)
  • 对主键或时间字段执行:SELECT MIN(id), MAX(id), COUNT(*) FROM t; —— 能快速发现截断、自增偏移、或 WHERE 条件漏写(如只导了 created_at > '2023-01-01' 却忘了补全)
  • 如果表有逻辑删除标记(如 is_deleted = 0),确认迁移脚本是否保留了该过滤逻辑

pt-table-checksum 做分块校验(适合大表或主从一致性检查)

当表超过千万行,CHECKSUM TABLE 太慢且锁表严重。pt-table-checksum(Percona Toolkit 提供)通过分块 + CRC32 + 主从复制机制,在不锁表前提下完成逐块校验,也适用于迁移后与原库的离线比对。

  • 需在源库运行,将校验结果写入指定表(如 percona.checksums),目标库需有同名库表可写入
  • 关键参数:--chunk-size 控制每块行数(默认约 1k 行),--replicate 指定结果表,--no-check-binlog-format 可绕过 binlog 格式限制(仅离线比对时安全使用)
  • 执行完后查 SELECT * FROM percona.checksums WHERE this_crc != master_crc OR is_drift != 0; —— 有结果即存在不一致
  • 它依赖主键或唯一索引分块,无主键表会退化为全表扫描,慎用

手动抽样比对具体字段值(防隐式类型转换/字符集问题)

校验和或行数一致 ≠ 数据真正一致。常见坑包括:源库 utf8mb4 目标库 utf8 导致 emoji 截断、timestamp 因时区设置不同而偏移、DECIMAL 精度丢失、NULL 与空字符串混淆。

  • 写一条带排序和 LIMIT 的语句,抽取头部、中部、尾部各几行:SELECT id, name, created_at, amount FROM t ORDER BY id LIMIT 100, 10;,分别在两库执行并肉眼或脚本比对输出
  • 重点检查:含中文、特殊符号、小数、时间字段的记录;主键相邻但业务上有关联的多行(比如订单+订单项)
  • HEX() 函数看实际字节:SELECT HEX(name) FROM t WHERE id = 123;,能暴露字符集降级导致的乱码或截断

实际迁移中,最容易被跳过的其实是 COUNT(*) 和字段抽样。校验和工具再强大,也掩盖不了导出时少加了 --where 或 mysqldump 忘了 --skip-triggers 这类低级失误。

text=ZqhQzanResources