datax避坑记录
先介绍一下datax,dataX 是阿里云 DataWorks数据集成 的开源版本,在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、HDFS、Hive、ADS、HBase、TableStore(OTS)、MaxCompute(ODPS)、Hologres、DRDS 等各种异构数据源之间高效的数据同步功能。
具体的使用方法其实官方的文档写得挺详细的,我就不做多余的重复了,这篇文章主要是写我使用datax时遇到的坑,就拿我之前用datax做mysql数据库的迁移做例子,另,附上官方地址:https://github.com/alibaba/DataX。
插件名称对应
reader和writer必须对应自己要进行数据同步的对象,比如要进行同步的是mysql数据库,那么job文件中reader和writer对应的name就必须配置为mysqlreader和mysqlwriter。这是一个小细节,因为datax的例子中写的是streamreader和streamwriter,如果复制过来,写job文件的时候忘记改,有时候也会花费些时间去找问题。
1000行限制
了解datax的都知道,用datax时,需要我们自己配置job文件,如下:
{
"job": {
"setting": {
"speed": {
"channel": 3,
"byte": 1048576
},
"errorLimit": {
"record": 0,
"percentage": 0.02
}
},
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "yRjwDFuoPKlqya9h9H2Amg==",
"password": "6YrK4y3NaUxccEgnoAz8yA==",
"column": [
"id",
"name",
"age",
"add_time"
],
"where": "add_time >= ${startTime} and add_time < ${endtTime}",
"splitPk": "",
"connection": [
{
"table": [
"student"
],
"jdbcUrl": [
"jdbc:mysql://127.0.0.1:3306/mytest?serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&useSSL=false&nullNamePatternMatchesAll=true&useUnicode=true"
]
}
]
}
},
"writer": {
"name": "mysqlwriter",
"parameter": {
"username": "yRjwDFuoPKlqya9h9H2Amg==",
"password": "6YrK4y3NaUxccEgnoAz8yA==",
"writeMode": "insert",
"column": [
"id",
"name",
"age",
"add_time"
],
"connection": [
{
"table": [
"student"
],
"jdbcUrl": "jdbc:mysql://127.0.0.1:3306/datax_test?serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&useSSL=false&nullNamePatternMatchesAll=true&useUnicode=true"
}
]
}
}
}
]
}
}
但是有可能会遇到明明有上万的数据,却只能读取到一千条,为啥呢,有可能是数据库默认限制了一次只能抽取1000条,这个时候可以使用querySql,通过limit解决。
{
"job": {
"setting": {
"speed": {
"channel": 3,
"byte": 1048576
},
"errorLimit": {
"record": 0,
"percentage": 0.02
}
},
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "yRjwDFuoPKlqya9h9H2Amg==",
"password": "6YrK4y3NaUxccEgnoAz8yA==",
"column": [
"id",
"name",
"age",
"add_time"
],
"splitPk": "",
"connection": [
{
"querySql":"select * from student limit 0,100000",
"jdbcUrl": [
"jdbc:mysql://127.0.0.1:3306/mytest?serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&useSSL=false&nullNamePatternMatchesAll=true&useUnicode=true"
]
}
]
}
},
"writer": {
"name": "mysqlwriter",
"parameter": {
"username": "yRjwDFuoPKlqya9h9H2Amg==",
"password": "6YrK4y3NaUxccEgnoAz8yA==",
"writeMode": "insert",
"column": [
"id",
"name",
"age",
"add_time"
],
"connection": [
{
"table": [
"student"
],
"jdbcUrl": "jdbc:mysql://127.0.0.1:3306/datax_test?serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&useSSL=false&nullNamePatternMatchesAll=true&useUnicode=true"
}
]
}
}
}
]
}
}
这样,可以一次性可以查询出100000条数据了,因为我是导全表数据,所以where条件也不需要。
批量执行
因为是数据库迁移,一般来说有个几百张表都是基本操作,如果我执行一个表的迁移就要去改一下job文件中的表名岂不是很麻烦吗,所以我去留意了一下datax的配置,发现table的配置是用的[],那感觉这里面应该是支持多表的。
emmm。。。那如果schema结构不一样怎么办,本来我要做的就是把这部分数据迁移到另一个数据库里。所以这里是有点麻烦,但是也不是没有办法解决,这里可以通过一个sh脚本去解决。
首先job文件需要调整一下,表名这些就不能固定死,要通过参数传递进来。因为我可以确定表的字段结构这些都是能一一对应的,column配置我就直接使用的*。
{
"job": {
"setting": {
"speed": {
"channel": 3,
"byte": 1048576
},
"errorLimit": {
"record": 0,
"percentage": 0.02
}
},
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "yRjwDFuoPKlqya9h9H2Amg==",
"password": "6YrK4y3NaUxccEgnoAz8yA==",
"column": ["*"],
"splitPk": "",
"connection": [
{
"querySql":"select * from ${source_table_name} limit 0,100000",
"jdbcUrl": [
"${source_db}"
]
}
]
}
},
"writer": {
"name": "mysqlwriter",
"parameter": {
"username": "yRjwDFuoPKlqya9h9H2Amg==",
"password": "6YrK4y3NaUxccEgnoAz8yA==",
"writeMode": "insert",
"column": ["*"],
"connection": [
{
"table": [
"${target_table_name}"
],
"jdbcUrl": "${target_db}"
}
]
}
}
}
]
}
}
说明一下sh脚本,我的datax安装目录:/data/lxf/datax,我写的job文件名为datasync.json,就放在datax的job目录下,tables.txt是我存放所有需要导的表名的文件,为了方便我也同样放在datax的job目录下,且两个数据库需要迁移的表的表名都是一样的。所以,最终sh脚本如下:
table_list='/data/lxf/datax/job/tables.txt'
exec_path='/data/lxf/datax/bin/datax.py'
source_db='jdbc:mysql://127.0.0.1:3306/mytest?serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&useSSL=false&nullNamePatternMatchesAll=true&useUnicode=true'
target_db='jdbc:mysql://127.0.0.1:3306/datax_test?serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&useSSL=false&nullNamePatternMatchesAll=true&useUnicode=true'
for table_name in cat $table_list
do
python $exec_path -p "-Dsource_table_name=$table_name -Dtarget_table_name=$table_name -Dsource_db=$source_db -Dtarget_db=$target_db" /data/lxf/datax/job/datasync.json
done
tables.txt的内容如下,有多少表写多少就行,一个表名一行:
student
user_info
role_info
以上就是我第一次使用datax遇到的一些坑,也用自己的办法解决了,希望对大家有用。