开发者社区> 问答> 正文

表字段位置改变,数据同步错乱

环境信息

canal version v1.1.3 mysql version v5.7.20 kafka version v1.0

问题描述

在同步mysql数据时,如果移动表字段位置,canal只捕获alter操作但没有处理,导致数据同步错乱。在canal --> kafka、adapter的hbase 均重现该问题

步骤重现

  1. 创建了一个hello库quniya4表

  2. 表里有三个字段(name,value,id)

  3. 我先建的name,value,最后建的id主键自增。现在我把id的位置移动到name、value的上面, 也就是说id的字段位置变成了 frist,现在的表字段位置为(id,name,value)

  4. 我插入数据(1,a,aaa)=> (aaa,1,a) ; name变成了1,value变成了a, 而id还是没有移动位置前的第三位,所以kafka消费这条数据时id=aaa,hbase亦是如此

预期结果

kafka预期显示:

{"data":[{"id":"1","name":"a","value":"aaa"}] ...}

实际执行情况

kafka结果显示:

{"data":[{"name":"1","value":"a","id":"aaa"}],"database":"hello","es":1553330817000,"id":20,"isDdl":false,"mysqlType":{"name":"varchar(255)","value":"varchar(255)","id":"int"},"old":null,"pkNames":["id"],"sql":"","sqlType":{"name":4,"value":12,"id":12},"table":"quniya4","ts":1553330817903,"type":"INSERT"}

hbase结果显示:

hbase(main):009:0> scan 'hello.quniya4' ROW COLUMN+CELL
ccc|3 column=cf:id, timestamp=1553331439400, value=ccc
ccc|3 column=cf:name, timestamp=1553331439400, value=3
ccc|3 column=cf:value, timestamp=1553331439400, value=c

原提问者GitHub用户alynnchen

展开
收起
古拉古拉 2023-05-08 13:44:11 125 0
2 条回答
写回答
取消 提交回答
  • 确认是tablemeta tsdb针对DDL支持问题,针对alter table quniya4 modify id int not null first

    原回答者GitHub用户agapple

    2023-05-09 17:46:33
    赞同 展开评论 打赏
  • 随心分享,欢迎友善交流讨论:)

    根据您的描述,如果在MySQL中移动表字段位置,Canal无法正确识别字段位置变更的变化,导致数据同步错乱。在Canal中,字段顺序是按照字段在MySQL表中定义的顺序进行处理的。如果表字段顺序发生变化,Canal无法正确解析数据,从而导致同步错误。

    为了解决这个问题,您可以尝试使用Canal的"row"模式进行同步。在"row"模式下,Canal会将每一行的数据解析成一个JSON对象,而不是按照列进行解析。这样,在表字段位置发生变化时,Canal仍然可以正确识别数据,并将其同步到目标系统中。

    要使用"row"模式进行同步,您需要在Canal的配置文件中设置canal.instance.mode参数为"row"。例如:

    canal.instance.mode=row 在这个例子中,我们使用"row"模式进行同步。这将使Canal将每一行的数据解析为一个JSON对象,并将其传输到目标系统中。

    如果您希望继续使用Canal的默认模式进行同步,并且仍然要处理表字段位置变化的问题,建议您在修改表字段位置时,同时修改Canal的配置文件,以反映这些变化。例如,如果您将"ID"字段移动到第一列,则可以按照以下方式修改Canal的配置文件:

    canal.instance.filter.regex=.*.quniya4 canal.instance.filter.black.regex=quniya4.(name|value) canal.instance.filter.druid.ddl = true 在这个示例中,我们使用canal.instance.filter.regex参数指定要包含的表的名称,使用canal.instance.filter.black.regex参数指定要排除的字段的名称。这样,Canal就会忽略"name"和"value"字段的变化,仅处理"ID"字段的变化。

    需要注意的是,这种方法可能会导致一些数据被忽略或丢失。因此,在进行修改之前,请确保您已经全面测试了这个修改,以确保不会引入其他问题。

    2023-05-08 13:50:34
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
MaxCompute技术公开课第四季 之 如何将Kafka数据同步至MaxCompute 立即下载
低代码开发师(初级)实战教程 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载