来个定场  

点扛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_noWHERE 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 备注了需要优化,那我们是不是得替他优化下,这个坑才算填平,但是如果何优化呢,会不会再挖个新坑?

坑一:canal 的一处TODO 引发的一地华子相关推荐

  1. 踩坑日记之Springfox+Kotlin lateinit引发NullPointException

    文章目录 相关技术栈 起因 分析 1. 报错位置 2. 接口定义 3. Kotlin编译成Java 4. springfox源码分析 1. 判断是否加了`@RequestBody`等参数 2. 包装` ...

  2. Android studio中todo的用法

    一 TODO 简介 二 Android Studio TODO 用法 添加 TODO 查看 TODO 完成 TODO 三 Android Studio FIXME 用法 添加 FIXME 筛选 FIX ...

  3. 如何设计一门语言(二)——什么是坑(b)

    我从来没有在别的语言的粉里面看见过这么容易展示人性丑陋一面的粉,就算是从十几年前开始的C++和C对喷,GC和非GC对喷,静态类型动态类型对喷的时候,甚至是云风出来喷C++黑得那么惊天动地的时候,都没有 ...

  4. 从转载阿里开源项目 Egg.js 技术文档引发的“版权纠纷”,看宽松的 MIT 许可该如何用?

    作者 | 苏宓.彭慧中 出品 | CSDN(ID:CSDNnews) 开源迅速发展的这两年,很多内部问题逐渐凸显出来,如安全.版权.协议使用等. 近日,来自V2EX社区中一位开发者 @an168ban ...

  5. mysql 二进制订阅神器 alibaba 的 Canal

    第 1 章 Canal 入门 1.1 什么是 Canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费. 阿里巴巴 B2B 公司,因 ...

  6. 黑马JAVA知识点总结

    一.黑马程序员-java概述与基础知识 6 1.何为编程? 6 2.Java语言概述,历史.特点 6 3.什么是跨平台性?原理是什么?JVM 7 4.Jre和Jdk的区别? 7 5.java虚拟机JV ...

  7. 1 Go语言开发环境搭建详细教程+go常见bug合集【Go语言教程】

    Go语言开发环境搭建[Win.Linux.Mac] 1 SDK下载 官网地址:golang.org,因为一些原因国内可能无法访问.可以使用下面第二个链接. 国内地址访问:https://golang. ...

  8. DCache DCache测试搭建

    文章目录 DCache测试搭建 简介 背景 支持平台 特点 组成 安装部署 tars框架 依赖环境 依赖安装 mysql部署 tars部署 DCache部署 项目待完善的问题 DCache测试搭建 简 ...

  9. DCache搭建测试

    DCache搭建测试 工作需要,提前熟悉下部署过程,如有错误还望指点. 简介 背景 Dcache使用腾讯Tars框架开发,属于分布式的NoSQL存储系统.数据存储在内存中,还可以连接后端DB做数据的持 ...

最新文章

  1. Cent OS – Tomcat 7 - 集群
  2. Theano - Numpy 新手
  3. Sql Server 2005 中的row_number() 分页技术
  4. PHP 两个页面跳转,session会失效?
  5. python 散点图 不同颜色_python – pandas – 每个点都有不同颜色图例的散点图
  6. Nginx启动/重启脚本详解
  7. 安装mongodb以及设置为windows服务 详细步骤
  8. 【linux】ubuntu更改mysql数据文件路径
  9. SpringBoot实战之文件上传微软云(Azure Storage)
  10. Android学习分享:执行某ViewGroup的动画时,子控件太多导致动画执行卡顿的问题...
  11. 【Python入门教程】第04篇 Hello World程序
  12. php设计超级玛丽人物,面向对象实现简单版的超级马里奥小游戏
  13. IOS 出现不支持的 URL
  14. 大连到日本出差/旅游注意事项
  15. service worker使用
  16. android 夏令时,android – jodatime如何知道夏令时是否开启
  17. 哈尔滨工业大学计算机科学与技术学院许博文,王轩-哈尔滨工业大学(深圳)计算机科学与技术学院...
  18. 子域名在线查询网站推荐
  19. 百练:4151 电影节
  20. chrome 打印布局_Chrome打印网页中的宽度控制

热门文章

  1. 2021年中国体育用品市场:耐克、阿迪后退,安踏持续向上破圈
  2. 一个算法笨蛋的12月leetCode刷题日记
  3. [P1860]新魔法药水
  4. linux 监听终端输入法,xinit 终端中文输入法
  5. 小甲鱼第016讲:序列!序列! | 课后测试题及答案
  6. java visual linux,如何在 Linux 中安装 Visual Studio Code
  7. 从零学Java(19)之 if else分支结构详解,小AD要搞对面心态!
  8. docker-compose docker容器编排插件
  9. Android基础 - Android Studio 添加游戏音效
  10. 【翻译】HyNet: Learning Local Descriptor with Hybrid Similarity Measure and Triplet Loss