环境信息
canal version: 1.1.3 canal adapter rdb: 1.1.3 mysql version:5.7.23
问题描述
使用Canal指定Position同步,由于Canal会将同步位置点提前(看之前的讨论提到是提前60秒、未来得及从代码端确认),会产生重复记录,进而导致Canal-Adapter-RDB报主键唯一错,阻塞复制过程
步骤重现
1.向两张表中分别插入一条数据:
insert into busi1 values (1, 'in', 'asdf', now()); insert into busi2 values (1, 'in', 'asdf', curdate());
2.使用mysqldump全量导出至目标Oracle数据库
3.根据show master status记录位置点,在canal的instance配置文件中设置对应position,本次测试position为1057
4.向一张表中插入一条数据:
insert into busi1 values (2, 'out', 'qwer', now());
5.启动canal
6.启动canal-adapter
7.检查canal-adapter日志,发现报错:
2019-05-23 15:50:22.157 [pool-8-thread-1] ERROR c.a.o.canal.adapter.launcher.loader.CanalAdapterWorker - java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.RuntimeException: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (TEST.PK_BUSI2) violated
java.lang.RuntimeException: java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.RuntimeException: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (TEST.PK_BUSI2) violated
at com.alibaba.otter.canal.client.adapter.rdb.RdbAdapter.sync(RdbAdapter.java:169)
at com.alibaba.otter.canal.adapter.launcher.loader.AbstractCanalAdapterWorker.batchSync(AbstractCanalAdapterWorker.java:198)
at com.alibaba.otter.canal.adapter.launcher.loader.AbstractCanalAdapterWorker.lambda$null$1(AbstractCanalAdapterWorker.java:62)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at com.alibaba.otter.canal.adapter.launcher.loader.AbstractCanalAdapterWorker.lambda$null$2(AbstractCanalAdapterWorker.java:58)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
8.该主键冲突会阻塞之后的busi1的第2条记录入Oracle库
9.如果去掉Oracle数据库上busi2的主键PK_BUSI2,会发现id为1的记录重复插入了两条
10.查看Canal日志:
2019-05-23 15:49:26.689 [destination = example , address = /192.168.100.25:3306 , EventParser] WARN c.a.o.c.p.inbound.mysql.rds.RdsBinlogEventParserProxy - ---> find start position successfully, EntryPosition[included=false,journalName=binlog.000009,position=961,serverId=11,gtid=,timestamp=1558596932000] cost : 2919ms , the next step is binlog dump 可见,起始点提前到961,比配置文件中的位置靠前
11.分析原因疑似Canal提前位置点,导致重复记录
期待结果
1.Canal复制的起始点按照配置文件中实际制定的position执行
2.Canal复制的起始点还采用提前的方式不变,目标数据库端通过主键限制重复记录,Canal-Adapter对主键冲突错误跳过不处理,或采用类似于数据库Merge语句的功能,如存在记录则按新记录更新
现执行情况
1.Canal复制的起始点比配置文件提前,导致数据重复
原提问者GitHub用户power225
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。