愉快的周末从加班开始结束. 今天有个数据迁移的事情, 通常我们使用mysqldump之类的来做
之前也做过这种迁移, 没啥问题. 但这次校验的时候发现有几张表checksum值不一致.
而且每过一段时间查询的checksum值都不一样, 退出重新登录查询的值总是在2个值直接来回变(蹦迪?). 那么这数据到底是否一致呢???
通常有如下几种可能:
首先把有问题的表导到测试环境, 发起校验看下. 发现校验值和源端/目标端都不一样. 这就有说法了, 看了下表结构,大概如下(已脱敏, 下面的表为模拟的表):
create table t20250607(
id bigint(20) not null,
a json,
b datetime not null default current_timestamp,
c int(11) not null default '1'
)
看起来最可疑的是default current_timestamp
, 但我们是mysqldump导出的, 所以值肯定是写入数据文件的, 而且checksum只发生变化后, ibd数据文件的时间戳并没有发生变化.
那么就还剩json
类型了, 于是我们单独模拟了一张表来测试:
create table t20250607_json(t json);
insert into t20250607_json values('{"key":"value"}');
checksum table t20250607_json;
-- 过一段时间,或者重新登录后再次校验
checksum table t20250607_json;
发现校验值确实不一样. 那就是json字段的问题了(查看了下其它不一致的表,均存在json字段). 查看了下官方BUG, 发现早在2017年就有大佬提出这个BUG了: https://bugs.mysql.com/bug.php?id=87847
原因也很简单, 就是json没有被当作字符串去计算. 8.0 没有这个BUG, 因为8.0是把json当作字符串处理的. 我们对比下源码(sql/sql_table.cc)就能看出来:
回到最开始的问题:数据是否一致? 既然checksum不可信了, 那我们可以使用Pt之类的工具, 或者自己校验下hash值也可以, 可参考如下方法:
select sha2(group_concat(concat(col1,col2,col3)),256) from tablename;
校验值也一致即可, 如果数据量大的话, 建议分chunk来做.
本次问题: 5.7存在json字段则导致checksum值不断变化
处理方法: 换校验方法
这个bug是2017年就有的, 但在5.7.44(最后一个版本)了都还没修复, 虽然就只需要加1行代码就行....
参考
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。