问题描述

新增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即可

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

  1. es 全量同步mysql_使用canal将mysql同步到es中

    因为自己项目中需要用到mysql数据同步到es中,查找了相关资料最后决定用canal来做,所以便有了本文,下面一起来看如何使用canal吧 canal教程 根据 https://github.com/ ...

  2. Canal Mysql binlog 同步至 Hbase ES

    文章目录 一.Canal介绍 工作原理 canal 工作原理 二.下载 三.安装使用 Mysql准备 canal 安装 解压缩 canal-deployer 配置修改 启动 查看server日志 查看 ...

  3. Elasticsearch7.9集群部署,head插件,canal同步mysql数据到es,亲自测试,无坑

    Elasticsearch集群部署 1.服务器规划 10.4.7.11 node1 10.4.7.12 node2 10.4.7.13 node3 1. 集群相关    一个运行中的 Elastics ...

  4. Elastic实战:canal自定义客户端,实现mysql多表同步到es

    0. 引言 我们之前讲解了利用canal实现无代码入侵的同步mysql数据到elasticsearch,并且讲解了主子表数据如何同步. 通过canal1.1.5实现mysql8.0数据增量/全量同步到 ...

  5. 利用Canal全量/增量同步mysql数据至ES

    Canal同步mysql数据至ES 1.更改Mysql配置 1.1 开启 Binlog 写入功能 配置 binlog-format 为 ROW 模式,配置my.cnf [mysqld] log-bin ...

  6. canal下载 linux_阿里canal数据库同步ES使用

    canal的概念这里我就不多说了,以下附上git链接查看:https://github.com/alibaba/canal 随笔记录一下我遇到的问题与修改,这里主要讲如何正确的配置: 首先,去官网下载 ...

  7. Mysql同步数据到Elasticsearch(实时Canal)

    这里只是作为一个想法,Canal有监听binlog文件的功能.所以简单看了一下Canal的入门使用. 后续Canal实时数据同步的功能希望不会被我阉割......当然有大佬已经实现或者有其他方法实现m ...

  8. 使用canal实时同步MySQL数据到Elasticsearch

    使用canal实时同步MySQL数据到Elasticsearch 搭建环境 安装 elasticsearch 安装 kibana 下载和安装canal 1.下载canal 2.配置MySQL 3.配置 ...

  9. canal实现mysql同步Elasticsearch数据linux中安装ELK

    linux中ELK数据同步 前言 ElasticSearch安装 下载安装包&&添加es用户 启动 ElasticSearch HEAD安装 下载&&安装 配置 设置跨 ...

最新文章

  1. 最新网络工程师考试大纲
  2. Zookeeper系列(十)zookeeper的服务端启动详述
  3. cms java垃圾回收_java cms垃圾回收器总结
  4. 打造自己的LinqProvider
  5. 容器编排技术 -- Kubernetes 为 Namespace 配置最小和最大 CPU 限制
  6. Servlet是否单例?
  7. Protobuffer和json深度对比
  8. mac下编译curl库(处理https的问题)
  9. 含有自增序列的表中使用truncate与delete的不同结果
  10. 2021【第十二届蓝桥杯省赛】 C/C++ B组(第一场)
  11. SPSS和excel数据分析之平均值和标准误差对比图
  12. QTTabBar我装好啦!
  13. MATLAB实现简单的聊天软件
  14. python做有道翻译接口的时候报UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 1: invalid sta
  15. Win10 关闭屏幕旋转(转向)
  16. 多媒体计算机的媒体信息包括文字,多媒体计算机中的媒体信息是指什么
  17. (转帖) cglib和jdk的区别
  18. Unity协程(Coroutine)之yield和迭代原理分析
  19. 带你了解ICCV、ECCV、CVPR三大国际会议
  20. 用Python实现微信定时发送消息

热门文章

  1. 工具用途_小工具大用途:万能扳手、开瓶器、开箱器,DIY16种用法,玩过吗
  2. pythonhash加密_Python字符串hashlib加密模块使用案例
  3. iphone分屏功能怎么用_iPhone上10个隐藏小技巧,怎么用怎么爽
  4. oracle 练习 50_萨克斯每天需要练习内容
  5. github gis 路径规划_Apollo问答丨车辆定位和轨迹规划用的是语义,还是3D Position?...
  6. 网页设计上机考试原题_全国计算机三级信息安全考试 经验分享
  7. 同包类 和 其他类 java_关于继承:为什么Java中的“protected”修饰符允许访问同一个包中的其他类?...
  8. vb.net 功能f8键事件_憋了三年,史上最全的 F1~F12 键用法整理出来了!
  9. typescript的类型描述_TypeScript类型声明书写详解
  10. 计算机网络学习笔记(一)——分层模型、协议、服务、连接模式、标准化组织