MySQL tinyint(1)类型数据在经过flink cdc同步到doris后只有0/1问题定位与解决
背景:
近期在负责公司数据仓库搭建事宜,踩了一些坑后,终于通了,目标报表也成功迁移到了新方案上,可在数据验收的时候发现,同一个订单查询出了多条记录,原本以为只是简单的left join出多条记录问题。
随着深入核实SQL、查询条件、表数据发现,同步后的数据表里的一个status字段全是0和1,而源表中有0 1 2 3 4等多个数值,起初以为是status为内置关键词或者内置列问题,去doris官方文档里没有查到这个,随即看了下这个字段的定义,是tinyint(1),于是我查看了名字为非关键词的同类型列,也出现了这个问题,同步后全是0和1,因此可以确认,tinyint(1)这个类型的字段从mysql使用flink cdc同步到doris会有问题。
同时查阅了doris同步后该数据的数据类型以及doris支持的数据类型后可知,这两个都是支持tinyint类型的,且内存占用都为1个字节。
继续查阅资料后发现,tinyint(1)相关有一个配置项为tinyInt1isBit=true(默认true),因此把这个字段认为是一个比特位,因此只有0和1。随即尝试将该列修改为tinyint类型,将同步任务停止,将脏数据删除,再次启动同步任务,同步好了之后查看数据已正常。
源表中该字段类型的值是有多个的
同步后的表里这个字段的值只有0和1了
select DISTINCT `status` from test2.ods_bid_bid_customer
查阅drosi表的字段类型是支持tinyint的
https://doris.apache.org/zh-CN/docs/table-design/data-type
mysql 数据类型
https://dev.mysql.com/doc/refman/5.7/en/data-types.html
搜索tinyint(1)相关的资料找到这个特性,可以得知确实有这种视为1比特只有0和1的情况
jdbc参数中文文档:https://www.cnblogs.com/EasonJim/p/7659475.html
英文官方文档:https://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html
原文位置:https://dev.mysql.com/doc/connector-j/en/connector-j-connp-props-result-sets.html#cj-conn-prop_tinyInt1isBit
发现问题后利用代码将mysql中所有表的DDL拿到,并搜索字段类型为tinyint(1)的字段类型,去除掉deleted等这种正常值确实只有0和1的字段,还剩下95个字段,分布在59个表中,以后都会有这个问题,于是利用代码生成目标SQL,并人工查看每个表的数据量进行评估,择机逐个执行修改字段类型从tinyint(1)到tinyint。做出SQL修改的时候一定要做评估,小心导致MySQL锁住不可用,小心主从之间行同步导致主从一直传输大量数据,转而引发生产环境崩溃。一般cdc监听变化的数据也要求主从库的同步模式要是row 行模式的。
如果你的表结构已经不方便修改的话,建议研究下给flink cdc mysql connector、jdbc url,目前看到的是到了doris中的数据已经是0和1了,不是我读取的时候未加tinyInt1isBit=false这个参数造成我看到的为0和1的。那么可以知道的是flink cdc在读取的时候出的问题导致读到的数据就是0和1了,可考虑加tinyInt1isBit=false参数或使用同版本的mysql connector(例如Driver for MySQL 8 and later https://www.mysql.com/products/connector/),驱动的版本不同、链接参数不同也是可能造成读取到的数据不同的。