Canal Mysql同步至ES/Hbase只有新增时生效,修改删除不生效

问题描述

新增Mysql数据时,ES、Hbase数据会同步成功;当删除Mysql数据,或者修改Mysql数据时同步ES、Hbase数据无变化(PS:修改和删除加上LIMIT xxx 就可以成功。)

问题分析

通过查看日志发现新增和删除记录的日志区别:新增data有数据,修改、删除 data为空

2021-09-22 10:29:03.551 [pool-1-thread-1] DEBUG c.a.o.c.client.adapter.hbase.service.HbaseSyncService - DML: {"data":[{"id":"d9a63f30-1b4c-11ec-99c4-708cb6f5eaa6","name":"aaabbbcccc","age":null,"age_2":null,"message":null,"insert_time":null}],"database":"test2","destination":"example","es":1632277742000,"groupId":"g1","isDdl":false,"old":null,"pkNames":["id"],"sql":"","table":"testsync","ts":1632277743140,"type":"INSERT"}
2021-09-22 10:19:36.703 [pool-1-thread-1] DEBUG c.a.o.c.client.adapter.hbase.service.HbaseSyncService - DML: {"data":null,"database":"test2","destination":"example","es":1632277176000,"groupId":"g1","isDdl":false,"old":null,"pkNames":[],"sql":"DELETE FROM testsync where name = 'aaabbbcccc'","table":"testsync","ts":1632277176566,"type":"DELETE"}
2021-09-22 10:19:36.704 [pool-1-thread-1] DEBUG c.a.o.canal.client.adapter.es.core.service.ESSyncService - DML: {"data":null,"database":"test2","destination":"example","es":1632277176000,"groupId":"g1","isDdl":false,"old":null,"pkNames":[],"sql":"DELETE FROM testsync where name = 'aaabbbcccc'","table":"testsync","ts":1632277176566,"type":"DELETE"} 

通过查看源码我们发现,当data为null时,直接return,不进行下一步操作

/*** 更新操作dml** @param config es配置* @param dml dml数据*/private void update(ESSyncConfig config, Dml dml) {List<Map<String, Object>> dataList = dml.getData();List<Map<String, Object>> oldList = dml.getOld();if (dataList == null || dataList.isEmpty() || oldList == null || oldList.isEmpty()) {return;}....

问题找到,原因就是我们没有记录修改的数据。
再次查看源码,找一下是从什么时候data没有的。
发现在MessageUtil中有数据转换,加入日志,重新打包将 connector.core-1.1.5.jar 替换掉,重启服务,我们查看下从数据接收进来是不是就已经没有了

/*** Message对象解析工具类** @author rewerma 2018-8-19 下午06:14:23* @version 1.0.0*/
public class MessageUtil {private static final Logger logger = LoggerFactory.getLogger(MessageUtil.class);public static List<CommonMessage> convert(Message message) {if (message == null) {return null;}List<CanalEntry.Entry> entries = message.getEntries();List<CommonMessage> msgs = new ArrayList<>(entries.size());for (CanalEntry.Entry entry : entries) {if (entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONBEGIN|| entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONEND) {continue;}CanalEntry.RowChange rowChange;try {rowChange = CanalEntry.RowChange.parseFrom(entry.getStoreValue());} catch (Exception e) {throw new RuntimeException("ERROR ## parser of eromanga-event has an error , data:" + entry.toString(),e);}// 加入日志,重新打包将 connector.core-1.1.5.jar 替换掉,重启服务,我们查看下从数据接收进来是不是就已经没有了logger.info("row:{}",rowChange.getRowDatasList());....

重启后在adapter日志中发现,在接收数据时已经没有了。

随后我们从 Mysql方面分析,根据Mysql Binlog三种格式我们知道,当类型设置Statement或者Mixed时会导致数据记录不是全部列。

这里简单介绍下三种区别

MySQL 5.5 中对于二进制日志 (binlog) 有 3 种不同的格式可选:Mixed,Statement,Row,默认格式是 Statement。总结一下这三种格式日志的优缺点。MySQL Replication 复制可以是基于一条语句 (Statement Level) ,也可以是基于一条记录 (Row Level),可以在 MySQL 的配置参数中设定这个复制级别,不同复制级别的设置会影响到 Master 端的 bin-log 日志格式。1. Row
日志中会记录成每一行数据被修改的形式,然后在 slave 端再对相同的数据进行修改。优点:在 row 模式下,bin-log 中可以不记录执行的 SQL 语句的上下文相关的信息,仅仅只需要记录那一条记录被修改了,修改成什么样了。所以 row 的日志内容会非常清楚的记录下每一行数据修改的细节,非常容易理解。而且不会出现某些特定情况下的存储过程或 function ,以及 trigger 的调用和触发无法被正确复制的问题。缺点:在 row 模式下,所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容,比如有这样一条 update 语句:UPDATE product SET owner_member_id = 'b' WHERE owner_member_id = 'a'
执行之后,日志中记录的不是这条 update 语句所对应的事件 (MySQL 以事件的形式来记录 bin-log 日志) ,而是这条语句所更新的每一条记录的变化情况,这样就记录成很多条记录被更新的很多个事件。自然,bin-log 日志的量就会很大。尤其是当执行 alter table 之类的语句的时候,产生的日志量是惊人的。因为 MySQL 对于 alter table 之类的表结构变更语句的处理方式是整个表的每一条记录都需要变动,实际上就是重建了整个表。那么该表的每一条记录都会被记录到日志中。2. Statement
每一条会修改数据的 SQL 都会记录到 master 的 bin-log 中。slave 在复制的时候 SQL 进程会解析成和原来 master 端执行过的相同的 SQL 再次执行。优点:在 statement 模式下,首先就是解决了 row 模式的缺点,不需要记录每一行数据的变化,减少了 bin-log 日志量,节省 I/O 以及存储资源,提高性能。因为他只需要记录在 master 上所执行的语句的细节,以及执行语句时候的上下文的信息。缺点:在 statement 模式下,由于他是记录的执行语句,所以,为了让这些语句在 slave 端也能正确执行,那么他还必须记录每条语句在执行的时候的一些相关信息,也就是上下文信息,以保证所有语句在 slave 端杯执行的时候能够得到和在 master 端执行时候相同的结果。另外就是,由于 MySQL 现在发展比较快,很多的新功能不断的加入,使 MySQL 的复制遇到了不小的挑战,自然复制的时候涉及到越复杂的内容,bug 也就越容易出现。在 statement 中,目前已经发现的就有不少情况会造成 MySQL 的复制出现问题,主要是修改数据的时候使用了某些特定的函数或者功能的时候会出现,比如:sleep() 函数在有些版本中就不能被正确复制,在存储过程中使用了 last_insert_id() 函数,可能会使 slave 和 master 上得到不一致的 id 等等。由于 row 是基于每一行来记录的变化,所以不会出现类似的问题。3. Mixed
从官方文档中看到,之前的 MySQL 一直都只有基于 statement 的复制模式,直到 5.1.5 版本的 MySQL 才开始支持 row 复制。从 5.0 开始,MySQL 的复制已经解决了大量老版本中出现的无法正确复制的问题。但是由于存储过程的出现,给 MySQL Replication 又带来了更大的新挑战。另外,看到官方文档说,从 5.1.8 版本开始,MySQL 提供了除 Statement 和 Row 之外的第三种复制模式:Mixed,实际上就是前两种模式的结合。在 Mixed 模式下,MySQL 会根据执行的每一条具体的 SQL 语句来区分对待记录的日志形式,也就是在 statement 和 row 之间选择一种。新版本中的 statment 还是和以前一样,仅仅记录执行的语句。而新版本的 MySQL 中对 row 模式也被做了优化,并不是所有的修改都会以 row 模式来记录,比如遇到表结构变更的时候就会以 statement 模式来记录,如果 SQL 语句确实就是 update 或者 delete 等修改数据的语句,那么还是会记录所有行的变更。

最后去查看我们配置文件,发现我们的配置文件设置了两个 binlog_format (复制之前的配置文件,在上面加了一个 binlog_format=ROW,但是未生效,被下面的覆盖了。。。。。)

最终删除

log_bin = mysql-bin 
binlog_format = mixed 

保留

log_bin=mysql-bin # 开启 binlog
binlog_format=ROW # 选择 ROW 模式
binlog_row_image=FULL

重启Mysql、canal 再次执行修改删除,data中已经有记录

2021-09-22 11:20:45.456 [pool-1-thread-1] DEBUG c.a.o.c.client.adapter.hbase.service.HbaseSyncService - DML: {"data":[{"id":"10d7e4b8-1b54-11ec-8673-708cb6f5eaa6","name":"bbb","age":null,"age_2":null,"message":null,"insert_time":1632280844000}],"database":"test2","destination":"example","es":1632280844000,"groupId":"g1","isDdl":false,"old":[{"name":"aaabbbcccc","insert_time":null}],"pkNames":["id"],"sql":"","table":"testsync","ts":1632280845389,"type":"UPDATE"}
2021-09-22 11:20:45.517 [pool-1-thread-1] DEBUG c.a.o.canal.client.adapter.es.core.service.ESSyncService - DML: {"data":[{"id":"10d7e4b8-1b54-11ec-8673-708cb6f5eaa6","name":"bbb","age":null,"age_2":null,"message":null,"insert_time":1632280844000}],"database":"test2","destination":"example","es":1632280844000,"groupId":"g1","isDdl":false,"old":[{"name":"aaabbbcccc","insert_time":null}],"pkNames":["id"],"sql":"","table":"testsync","ts":1632280845389,"type":"UPDATE"} 

文章开头有说:PS:修改和删除加上LIMIT xxx 就可以成功。原因就是ROW和mixed的区别。

其他类似问题

在这里插入图片描述

当为mixed时,在Navicat直接点+新增数据时data也同样为空。改为ROW即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/509631.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LinkedHashSet类

List接口: 允许元素重复,记录先后添加顺序. Set接口: 不允许元素重复,不记录先后添加顺序. 需求: 不允许元素重复,但是需要保证先后添加的顺序. LinkedHashSet:底层才有哈希表和链表算法. 哈希表:来保证唯一性,.此时就是HashSet,在哈希表中元素没有先后顺序. 链表: 来记录…

Canal Mysql binlog 同步至 ElasticSearch 详细介绍

文章目录数据同步ElasticSearch单表基本配置适配器映射文件详细介绍&#xff08;单表、多表映射介绍&#xff09;单表映射索引示例sql单表映射索引示例sql带函数或运算操作多表映射(一对一, 多对一)索引示例sql多表映射(一对多)索引示例sql其它类型的sql示例注意事项本文详细介…

基于C++11的线程池

背景 在传统的收到任务即创建线程的情况下&#xff0c;我们每收到一个任务&#xff0c;就创建一个线程&#xff0c;执行任务&#xff0c;销毁线程&#xff0c; 我们把这三个过程所用的时间分别记做T1,T2,T3 任务本身所用的时间仅占T2/(T1T2T3),这在任务本身所用时间很短的情况下…

集合的工具类

集合操作的工具类: 1):Arrays类: 2):Collections类. Arrays类: 在Collection接口中有一个方法叫toArray把集合转换为Object数组. 把集合转换为数组: Object[] arr 集合对象.toArray(); 数组也可以转换为集合(List集合): public static List asList(T… a) 等价于public …

Docker入门到精通开发指南(一文搞懂)

文章目录安装官方安装文档具体安装步骤1.卸载之前的版本(如果之前未用过忽略该步骤)2.安装相关依赖3.设置docker镜像4.安装docker安装latest版本指定版本安装5.启动docker6.查看docker版本7.运行一个docker hello world8.卸载docker9.配置阿里云镜像加速地址docker常用命令dock…

如何向Maven中央仓库提交自己的Jar包(发布自己的Jar包到中央仓库)

文章目录注册账号GPG 安装安装生成密钥上传公钥Maven配置上传到Maven仓库修改项目的配置&#xff0c;填写基本信息执行编译命令登录网站配置发布项目中应用遇到的问题解决方法本文将介绍如何将自己的jar包发布至公共的中央仓库&#xff0c;通过maven方式进行引用 注册账号 注册…

List和Set以及Map的选用

选用哪一种容器取决于每一种容器的存储特点以及当前业务的需求: List: 单一元素集合. 允许元素重复/记录元素的添加顺序. Set:单一元素集合. 不允许元素重复/不记录元素的添加顺序. 既要不重复,又要保证先后顺序:LinkedHashSet. Map: 双元素集合. 如果存储数据的时候,还得…

Map集合类

映射的数学解释: 设A、B是两个非空集合&#xff0c;如果存在一个法则f&#xff0c;使得对A中的每个元素a&#xff0c;按法则f&#xff0c;在B中有唯一确定的元素b与之对应&#xff0c;则称f为从A到B的映射&#xff0c;记作f&#xff1a;A→B。 映射关系(两个集合):A集合和B集…

Socket select模型

Windows socket select模型开发。 套接字select模型是一种比较常用的IO模型。利用该模型可以使Windows socket应用程序可以同时管理多个套接字。 使用select模型&#xff0c;可以使当执行操作的套接字满足可读可写条件时&#xff0c;给应用程序发送通知。收到这个通知后&#x…

Set实现类性能对比

Set接口的实现类: 共同的特点: 1):都不允许元素重复. 2):都不是线程安全的类. 解决方案:Set s Collections.synchronizedSet(Set对象); HashSet: 不保证元素的先后添加顺序. 底层才有的是哈希表算法,查询效率极高. 判断两个对象是否相等的规则: 1):equals比较为true. …

HugeGraph Server/Hubble安装使用

文章目录HugeGraph Server1 概述2 依赖2.1 安装JDK-1.83 部署3.1 下载tar包4 安装启动4.1 解压4.2 配置Hbase5 访问Server5.1 服务启动状态校验6 停止Server7 多图配置HugeGraph-Hubble 基于Web的可视化图形界面1.概述2.安装3 使用3.1创建图HugeGraph Server 1 概述 HugeGrap…

Mysql 集群双主双从安装使用详细讲解

文章目录下载Mysql安装单机Mysql配置Mysql集群双Master配置master1配置master2配置配置说明双Slave配置Slave1配置Slave2配置双 Master 机上创建账号&#xff0c;并授权远程复制查询Master1的状态查询Master2的状态双Slave机上执行 change master 同步Master数据Slave1 复制 Ma…

ElasticSearch 新增节点,横向扩容

文章目录查看当前ES状态新增节点配置遇到的问题查看当前ES状态 这里默认都是在Kibana进行操作 GET _cluster/health{"cluster_name" : "bjga-gz","status" : "yellow","timed_out" : false,"number_of_nodes" :…

输入和输出(IO)概述

什么是IO:(Input/Output):输入和输出. IO设备: 和电脑通信的设备. 输入设备:麦克风,扫描器,键盘,鼠标等. 输出设备:显示器,打印机,投影仪,耳机,音响等. 为什么程序需要IO呢? 案例1:打游戏操作,得分比较高,存储游戏的信息(XXX-888分). 此时需要把游戏中的数据存储起来,只能…

java中有关文件流的操作

文件流: 顾名思义,程序和文件打交道. 此时我们谈及的文件,值得是纯文本文件(txt的,不要使用Word,Excel), 在字节流中,暂时不要使用中文. FileInputStream: 文件的字节输入流 FileOutputStream: 文件的字节输出流 FileReader:文件的字符输入流 FileWriter:文件的字符输出流…

数据结构实验之二叉树一:树的同构

题目描述 给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2&#xff0c;则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的&#xff0c;因为我们把其中一棵树的结点A、B、G的左右孩子互换后&#xff0c;就得到另外一棵树。而图2就不是同构的。 图1 …

java中字符编码详解

字符编码的发展历程: 阶段1: 计算机只认识数字,我们在计算机里一切数据都是以数字来表示,因为英文符号有限, 所以规定使用的字节的最高位是0.每一个字节都是以0~127之间的数字来表示,比如A对应65,a对应97. 这就是美国标准信息交换码-ASCII. 阶段2: 随着计算机在全球的普及…

java中的包装流和缓冲流概述

处理流/包装流(相对于节点流更高级)装饰设计模式/包装模式: 1:隐藏了底层的节点流的差异,并对外提供了更方便的输入/输出功能,让我们只关心高级流的操作. 2:使用处理流包装了节点流,程序直接操作处理流,让节点流与底层的设备做IO操作. 3:只需要关闭处理流即可. 包装流如何区…

转换流和内存流

转换流:把字节流转成字符流: InputStreamReader:把字节输入流转成字符输入流. OutputStreamWriter:把字节输出流转成字符输出流. 为什么有字节转字符流,没有字符转字节流. 字节流可以操作一切文件(纯文本文件/二进制文件).字符流是用来操作中文纯文本使用的,本身是对字节流的…