都是空格惹的祸
作者: navyaijm2017 原文来源:https://tidb.net/blog/0b574914
背景
通过 DM 同步 Mysql 库到 Tidb 集群,在一个 DM-Worker 上启动两个 task,一个 task 同步到 3.0.14 的集群,另一个 task 同步到 4.0.4 的集群,两个集群分别给不同的业务部门使用
问题
4.0 集群上的开发人员反馈有一个查询 SQLselect id,wo_id,delivery_code,vehicle_order_id FROM insurance_wo where vehicle_order_id = '184742761197489224';
在 Tidb 上查到的数据不对,少数据了,这个少数据指的是和源头 Mysql 上的查询结果对比,在 Tidb 上的查询结果少一条数据。
复现
我用上面 SQL 在源 Mysql 上查询结果有两条数据:
我用上面 SQL 在 4.0 的 Tidb 上查询确实只查到了一条数据
然后我又用上面 SQL 在 3.0 的 Tidb 上查询发现也是只有一条数据
排查
第一个想到的是不是经过 DM 同步中间数据丢了呢,然后我把这个表从 Mysql 上通过 Mysqldump 导出来,导入到 Tidb 用上面 SQL 查询也是少一条数据,那么排除了 DM 的问题
我把上面信息反馈给 PingCAP 的同学继续排查, 首先通过
use index
对比查询走索引和表查询的情况,发现走索引查询和表查询结果都一样,都是有问题的
至此 PingCAP 的技术支持小伙伴需要后端研发人员介入了,又收集了一下 Tidb 集群的排序规则
用 Mysql 客户端登录 Tidb 的时候增加两个参数
--column-type-info
和--comments
执行下面 SQL:
–column-type-info 在结果中显示元数据信息
–comments 是否在发送到服务器的语句中剥离或保留注释, 默认值为跳过注释 ; 在连接 Tidb 的时候最好加上这个参数,不然有注释的 SQL,比如强制走索引,设置会不生效
通过下面 SQL 确认 where 条件 vehicle_order_id 这个字段值的长度, 发现有长度是 19 位的值,大部分都是 18 位的,说明 19 位的数据有点不正常
在 Tidb 上通过
hex
函数查看 vehicle_order_id 的十六进制,看看上面两条数据有啥区别,发现在 Tidb 上少的这条数据的十六进制的值最后多了一个20
,然后在 Mysql 上查询结果和 Tidb 上是是一样的。通过上面的验证,PingCAP 的后端技术人员基本推断这条 Tidb 上查询不到的数据
vehicle_order_id
这个字段内容里面应该是有一个空格,然后通过下面方法验证空格的 16 进制确实是20
OK,至此已经定位到问题的原因是数据内容里面有空格,Tidb 和 Mysql 对空格的处理逻辑不一样,那么如何解决问题呢,有两个方案:
数据里面有空格是不正常的,从 Mysql 源头定位到问题并修正,清洗库里面现在的数据把空格去掉, 清洗 SQL:
新建 4.0 的 Tidb 集群并开启新框架的排序规则
new_collations_enabled_on_first_bootstrap
,重新通过 DM 同步数据到新集群,业务切割到新集群。
新框架的排序规则目前只有在新建集群的时候才能开启,已经跑了业务的集群无法开启,官方后面会支持老集群开启这个功能
更多学习和交流可以关注我公众号:
版权声明: 本文为 InfoQ 作者【TiDB 社区干货传送门】的原创文章。
原文链接:【http://xie.infoq.cn/article/d4bd4edc67e1f16454bd0ac0f】。文章转载请联系作者。
评论