canal-1.1.6-hotfix-1 版本
canal-adapter 同步es偶现数组越界异常 java.lang.IndexOutOfBoundsException: Index: 13, Size: 13
ERROR c.a.otter.canal.adapter.launcher.loader.AdapterProcessor - java.lang.IndexOutOfBoundsException: Index: 13, Size: 13
java.lang.RuntimeException: java.lang.IndexOutOfBoundsException: Index: 13, Size: 13
at com.alibaba.otter.canal.client.adapter.es.core.service.ESSyncService.sync(ESSyncService.java:112) ~[na:na]
at com.alibaba.otter.canal.client.adapter.es.core.service.ESSyncService.sync(ESSyncService.java:60) ~[na:na]
at com.alibaba.otter.canal.client.adapter.es.core.ESAdapter.sync(ESAdapter.java:104) ~[na:na]
at com.alibaba.otter.canal.client.adapter.es.core.ESAdapter.sync(ESAdapter.java:83) ~[na:na]
at com.alibaba.otter.canal.adapter.launcher.loader.AdapterProcessor.batchSync(AdapterProcessor.java:140) ~[client-adapter.launcher-1.1.6.jar:na]
at com.alibaba.otter.canal.adapter.launcher.loader.AdapterProcessor.lambda$null$1(AdapterProcessor.java:98) ~[client-adapter.launcher-1.1.6.jar:na]
at java.util.concurrent.CopyOnWriteArrayList.forEach(CopyOnWriteArrayList.java:891) ~[na:1.8.0_181]
at com.alibaba.otter.canal.adapter.launcher.loader.AdapterProcessor.lambda$null$2(AdapterProcessor.java:95) ~[client-adapter.launcher-1.1.6.jar:na]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_181]
排查发现是,如果canal-server的instance配置了canal.instance.filter.field配置项 com.alibaba.otter.canal.client.adapter.support.MessageUtil 类型的messageConverter方法将rowchangeList数据转为dml时,可能会导致data列表的长度大于old列表,从而导致canal-adapter解析数组越界
重现的场景如下
- 例如批量更新3条记录,且第一条更新不在canal.instance.filter.field配置项里的字段
- 第一次循环 MessageUtil 里rowData.getAfterColumnsList()获取的columns列表元素的getUpdated都为false,updateSet也为空,导致后面old不会添加oldRow,最终data长度为3,old长度为2
还有一个问题,就是updateSet放在了for循环外,并且记录哪些字段更新,但是循环处理完,没有清空,可能会导致columns字段里即使没有变化的字段,也会将oldRow添加old中,消费端获取的dml 里old的旧值和data里新值一样,也尝试去做同步,虽然影响不大,但是最好是更新记录变化的字段,如果没有出现在canal.instance.filter.field配置项里,可以不生成dml,或者adapter不做同步。
1条答案
按热度按时间ef1yzkbh1#
遇到了同样的问题,在使用update table1 a table2 b xxx set b.field = xxx where a.x = b.x语法时,解析出来的rowChange中部分记录中所有字段updated为false,导致data和old的size不一致,adapter端报IOOBE