当设置mirrorDb: true整库映射,全量同步的接口会报错
这是我的mytest_user.yml配置文件,canal-adapter-1.1.5
#dataSourceKey: defaultDS
#destination: example
#groupId: g1
#outerAdapterKey: mysql1
#concurrent: true
#dbMapping:
# database: mytest
# table: user
# targetTable: mytest2.user
# targetPk:
# id: id
## mapAll: true
# targetColumns:
# id:
# name:
# role_id:
# c_time:
# test1:
# etlCondition: "where c_time>={}"
# commitBatch: 3000 # 批量提交的大小
## Mirror schema synchronize config
dataSourceKey: defaultDS
destination: myInstance
groupId: g1
outerAdapterKey: mysql1
concurrent: true
dbMapping:
mirrorDb: true
database: my-test
commitBatch: 1000
设置mirrorDb: true为整库映射,当我执行全量同步的接口会报错,
curl http://127.0.0.1:8081/etl/hbase/mysql1/mytest_person2.yml -X POST -d "params=2018-10-21 00:00:00"
报错信息:
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-test.null) _CNT' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_102]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_102]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_102]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_102]
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) ~[mysql-connector-java-5.1.48.jar:5.1.48]
at com.mysql.jdbc.Util.getInstance(Util.java:408) ~[mysql-connector-java-5.1.48.jar:5.1.48]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:944) ~[mysql-connector-java-5.1.48.jar:5.1.48]
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3933) ~[mysql-connector-java-5.1.48.jar:5.1.48]
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3869) ~[mysql-connector-java-5.1.48.jar:5.1.48]
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2524) ~[mysql-connector-java-5.1.48.jar:5.1.48]
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2675) ~[mysql-connector-java-5.1.48.jar:5.1.48]
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2465) ~[mysql-connector-java-5.1.48.jar:5.1.48]
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1912) ~[mysql-connector-java-5.1.48.jar:5.1.48]
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2020) ~[mysql-connector-java-5.1.48.jar:5.1.48]
at com.alibaba.druid.pool.DruidPooledPreparedStatement.executeQuery(DruidPooledPreparedStatement.java:227) ~[druid-1.2.6.jar:1.2.6]
at com.alibaba.otter.canal.client.adapter.support.Util.sqlRS(Util.java:59) ~[classes/:na]
将源码拉下来,本地debug发现,RdbEtlService.importData(List<String> params) 这个方法好像有点问题:
/**
* 导入数据
*/
public EtlResult importData(List<String> params) {
DbMapping dbMapping = config.getDbMapping();
String sql = "SELECT * FROM " + dbMapping.getDatabase() + "." + dbMapping.getTable();
return importData(sql, params);
}
这里既然是整表映射,那么 dbMapping.getTable()必然是拿不到值的,拼接的sql肯定会有问题。肯定会报错,难道整表映射就不支持全量同步接口?
根据我自己的测试,虽然mirrorDB=true的时候,增量同步已经是按库同步了,但如果想要用全量同步工具,就必须按table编写yml文件。也就是说,要专门为全量同步工具写一个表级别的yml文件。
另外,从同步原理来说,更新数据一定要知道PK是啥,那么就必须是按表来描述的。
因为业务需求同步两边的库名和名表也是一样的。于是我想用mirrorDB=true按库同步,目的就是不想一个个表的写yml文件,假设同步的表有很多,此时俺库同步应该是最佳选择
我测下来canal并不会识别PK然后自动按PK做同步,所以估计还是得自己写yml文件,当然也可以自己弄个脚本批量创建yml。
另外我们在实际使用中发现,canal在做大表ddl同步的时候有可能会因为sql执行超时而认为语句执行失败,然后就重试它。大的DDL一般来说总是超时的,就会卡队列。 我不太熟悉druid,要是您知道怎么修改它的执行超时时间,望不吝赐教
这个问题,一定要写所有表的yml吗?有更好的解决方案吗?
我mirrorDb: true时,从 数据库aa同步到 aa_1都不支持, 害得改源码。。 全量同步准备手动 nav icat导一下
好像是这样的。坑的很呐