坑一:canal 的一处TODO 引发的一地华子

来个定场  

点扛start 一时爽,日志报错眼环铃,搞不清楚东,猜不明白西,全无头绪急急急,哎呀~嗒~我去~


 提要: 

        业务场景:纸质票据的打印记录(order_print_record)与OCR技术识别纸质票据的采集记录(order_collection_record_0)做left join 关联查询;

        因系统是分库分表,2个db实例 15个库(其它不此处展开),需要做数据归并后高级查询,引入了es做高级搜索、cana做mysql binlog 异步监听,canal将mysql数据重放到 ES 索引中。 

坑景复现:       


       ES新建索引,如下图两个关联表(业务建模关系 :order_collection_record为从表,order_print_record为主表,一条打印记录,可以关联多条识别采集记录,1:n)

 

非坑1: ​​canal配置新表的 ESMapping


如下:(SQL中隐藏的些多余的东西,便于理解方便,请跟上我的良苦,若此良苦不好理解,请尽力理解,咯咯咯~)

【名词解释1:ESMapping为canal中定义的上图右侧的配置信息】,源码如下: 

非坑 2 :​​


        因业务查询主维度为从表(order_collection_record),故 DDL中 FROM 的 MainTable变为 order_collection_record表。认真看,下图中的 "注意this op",这个 mainTable的别名,就是坑眼儿!!!

【名词解释2:MainTable为canal中定义的SQL解析的主表,即FROM 关键词后的第一个表】,源码如下:

坑来了:

        进入/canal.adapter/bin 点扛restart.sh后一切正常,但在向 order_collection_record 或 order_print_record 表中 insert or update 操作数据时,出错了:

INFO  c.a.o.canal.client.adapter.es.core.service.ESSyncService - Sync 耗时: 0 ms,destination: order_center_db12, es index: order_collection_record, 操作类型 type :INSERT
ERROR com.alibaba.otter.canal.client.adapter.support.Util - sqlRs has error, 
		sql: SELECT op.id AS _id, op.id AS op_id,op.collection_id AS op_collection_id, op.collection_no AS op_collection_no,
					oc.id AS oc_id, oc.collection_id AS oc_collection_id,oc.collection_no AS oc_collection_no 
				FROM order_print_record_0 op 
				LEFT JOIN order_collection_record_0 oc ON op.collection_no = oc.collection_no
				WHERE op_collection_id=?  
ERROR c.a.o.canal.client.adapter.es.core.service.ESSyncService - sync error, es index: order_print_record, DML : Dml{destination='order_center_db12', database='......-12', table='order_collection_record_0', type='INSERT',......
ERROR c.a.otter.canal.adapter.launcher.loader.AdapterProcessor - java.lang.RuntimeException: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'op_collection_no' in 'where clause'
java.lang.RuntimeException: java.lang.RuntimeException: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'op_collection_no' in 'where clause'
	at com.alibaba.otter.canal.client.adapter.es.core.service.ESSyncService.sync(ESSyncService.java:128) ~[na:na]
	at com.alibaba.otter.canal.client.adapter.es.core.service.ESSyncService.sync(ESSyncService.java:64) ~[na:na]
	at com.alibaba.otter.canal.client.adapter.es.core.ESAdapter.sync(ESAdapter.java:115) ~[na:na]
	at com.alibaba.otter.canal.client.adapter.es.core.ESAdapter.sync(ESAdapter.java:94) ~[na:na]
	at com.alibaba.otter.canal.adapter.launcher.loader.AdapterProcessor.batchSync(AdapterProcessor.java:139) ~[client-adapter.launcher-1.1.5-SNAPSHOT.jar.bak_2021-4-7:na]
	at com.alibaba.otter.canal.adapter.launcher.loader.AdapterProcessor.lambda$null$1(AdapterProcessor.java:97) ~[client-adapter.launcher-1.1.5-SNAPSHOT.jar.bak_2021-4-7: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:94) ~[client-adapter.launcher-1.1.5-SNAPSHOT.jar.bak_2021-4-7: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]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]
Caused by: java.lang.RuntimeException: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'op_collection_no' in 'where clause'
	at com.alibaba.otter.canal.client.adapter.support.Util.sqlRS(Util.java:65) ~[client-adapter.common-1.1.5-SNAPSHOT.jar:na]
	at com.alibaba.otter.canal.client.adapter.es7x.support.ES7xTemplate.updateByQuery(ES7xTemplate.java:133) ~[na:na]
	at com.alibaba.otter.canal.client.adapter.es.core.service.ESSyncService.joinTableSimpleFieldOperation(ESSyncService.java:588) ~[na:na]
	at com.alibaba.otter.canal.client.adapter.es.core.service.ESSyncService.insert(ESSyncService.java:188) ~[na:na]
--

把报错的sql拿到客户端执行下,确实有问题

坑顶:

         这个unkonw column 如果是op.collection_id就对了,那么为什么只取到了【Field】的别名,没有取到真下有列名,且没有取到【MainTable】 的别名?

        难道配置有错误,有人为失误?遂check各个配置,出乎意料,没毛病,没毛线的头!!!

        难道配置没问题,进入思路不对?so, see see 源码        ,看看这个错误的来源吧~

        从 ”sqlRs has error“入手,简单直接,可叹,有句名言"知识总在需要时才被重视"!

再结合ERROR日志的信息

在本地看的是master分支代码,与图中ES7xTemplate 类 错误位置的 133行 不太匹配,去gitee上找到对应版本1.1.5核实下:

 跟本地的mster一样的位置,一样的对不上,再结合 ”sqlRs has error“所在方法,遂定位到问题应该在130行,然貌似还是没有毛线球的头!!!

坑道:

再向上看看,咦!貌似有根毛线:

        按道理(源码)我们上面错误的sql应该是被包裹成子查询的,但明显错误日志中我们拿到的sql的特征不符合些处逻辑~呃~~~ 得来根华子冷静下,传说中的诡异事件?

        一根一根的华子,提醒我:事出必有因! 

        第二天在一顿(≈1天)配置级别信息比对、测试环境配置文件拷贝到 生产、生产环境配置文件拷贝到测试,总结 了一个很无力的线索:测试环境正常,生产环境必现。

        此时领导来了,需要给业务一个既定的时间方案,不让业务无限期等待(别在身后催)。

此时产生了三个并行解决思路

        一是锁定在环境差异方向上,继续比对其它没比对的文件

        二是直接拷贝测试环境的canal.adapter到生产环境的新机器试试效果(与正常环境隔离,防止 影响正常业务),没问题的话直接投产使用,慢慢再找问题

        三是用笨方法,放弃canal,写15个job轮询增量标识字段(确实很笨)

坑底:

吭哧吭哧~咦,看下图

比对到plugin文件上夹下的:client-adapter.es7x-1.1.5-SNAPSHOT-jar-with-dependencies.jar,

终于找到了问题,还真是"坑道"。

呃,原来是有人在此挖了个坑,贴了个符!!!

这个坑之前的大作同事没想起来,我给他截图,他才想起来,当前他发现效率低,发现源码作者有个todo备注:

遂就把源码修改了下,成了个定制版本。

出坑:

           既然源码作者 todo 备注了需要优化,那我们是不是得替他优化下,这个坑才算填平,但是如果何优化呢,会不会再挖个新坑?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值