常见问题_HX产品合作手册

Datax 使用过程中碰到的一个“BUG”?


问题描述:

如上图所示,源端是MySQL,其中有year数据类型。目标端没有year类型,所以需要转成成其它类型。通过官方手册中的描述:“The YEAR type is a 1-byte type used to represent year values. It can be declared as YEAR with an implicit display width of 4 characters, or equivalently as YEAR(4) with an explicit display width.” 我们把对等替换成了char(4)数据类型。

通过DataX迁移完成后,没有任何报错,但是在校验数据时,发现数据不一致的情况。在字段“nian”,默认值为null或者输入错误值“”时,写到目标库时,变成了0.这肯定是不对的。那么问题到底出现在哪里呢?

原因查找:

1、重新又翻了下,关于year数据类型的相关说明


特别注意:year在DataX中,不是date类型,而是按照String来处理的。

2、去查看相关的源码:

因为是从MySQL读出来的数据,所以去mysqlreader目录下查找相关的源码。首先要查看的是“
mysqlreader--SNAPSHOT.jar”的jar包,后来发现其用到了如下的jar包:


所以有去下载对应的jar包。“
datax-common--SNAPSHOT.jar” 和 “
plugin-rdbms-util--SNAPSHOT.jar”两个包,查看后,发现common都是些通用的class,没有reader相关的。于是重点查看“
plugin-rdbms-util--SNAPSHOT.jar”。

从GitHub上下载对应的源码文件,通过发现后,总算找到了对应的Class。


com.alibaba.datax.plugin.rdbms.reader.CommonRdbmsReader。


如图,关于year类型的处理方式,如果是year,那么就赋值 rs.getInt(i)。那么它和0有什么关系呢?因为我对Java仅仅是一知半解,所以做了个测试。


因为year在Datax中中是安装string的方式来处理的,而year又存储的是数字。所以模拟的表中sex为char类型,且存入的值为1和默认的null。通过java程序,取出来后,发现null值,对应的为0。那么迁移过程中的疑惑也就解决了。


“”变“0”问题跟踪

通过上面的分析,已经解答了,为什么默认值,会变为0的问题发生。那么“”为甚什么也会变成0呢?

通过查看DataX的日志,我们发现其在MySQL的url中添加了一些连接参数,如下:

jdbc:mysql://:/test?allowMultiQueries=true&useSSL=false&yearIsDateType=false&zeroDateTimeBehavior=convertToNull&tinyInt1isBit=false&rewriteBatchedStatements=true


通过url中的“zeroDateTimeBehavior=convertToNull”,很明显,我们可以看到,如果碰到格式为0的,那么他会处理为null,变成null后,就回到了我们跟踪的代码分析那里,变成了0。所以就解答了,上面的问题。

问题解决

既然找到了原因,只需要对其做一些处理即可。对返回值为0的单独处理即可。修改后的代码见下图:

变更前的代码:


变更后的代码:

                    case Types.DATE:
                        if (metaData.getColumnTypeName(i).equalsIgnoreCase("year")) {
                           // record.addColumn(new LongColumn(rs.getInt(i)));
                           if (rs.getInt(i)==0){
                                        record.addColumn( new StringColumn(""));
                                } else {
                                        record.addColumn(new LongColumn(rs.getInt(i)));
                                }
                        } else {
                            record.addColumn(new DateColumn(rs.getDate(i)));
                        }
                        break;

验证结果


完美解决这次迁移所碰到的问题。

问题小结

  1. 由于在连接MySQL的过程中,在jdbc串中,自动添加了“zeroDateTimeBehavior=convertToNull”,所以在碰到 这种格式的时候,会自动转换成null。
  2. DataX 对year格式的处理,按照String来进行处理,因为year类型存储的是数字,所以在迁移的时候,查询出来的语句结果,在碰到year时,会通过getInt(i)的方式来取值,正常情况下时没问题。
  3. 在特殊情况下,比如没有值或者值为0格式时,getint(i)的返回结果为0,所以迁移到新的机器时,这两种情况的值会变为0,导致数据不一致的情况发生。此种问题的解决方式,只需要在对应的地方,添加对返回值为0的处理方式即可。
原文链接:,转发请注明来源!