V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
bluebo
V2EX  ›  程序员

写了一个 mysql cdc table,有用么

  •  
  •   bluebo · 170 天前 · 1545 次点击
    这是一个创建于 170 天前的主题,其中的信息可能已经有所发展或是发生改变。

    基于 mysql 的存储插件,与 mysql 的 binlog 开发了一个 mysql cdc table 。可以在 mysql select binlog 中表的变化数据

    __op

    0 – delete data

    1 – insert data

    2 – update before data

    3 – update after date

    __gtid

    全局事务 id

    __tm

    row event 发生的时间

    效果大概是这样

    https://madbluecat.github.io/post/mysqlcdctable/

    第 1 条附言  ·  170 天前
    __tm, 或者__gtid 可以看作是同步的水位线,
    __op 对应操作,
    再根据表里的实际内容 可以封装成其他数据库的 sql 实现增量同步
    26 条回复    2024-06-18 15:17:28 +08:00
    akin520
        1
    akin520  
       170 天前
    虽然不知道是什么东西,感觉就是高大上的东西
    bluebo
        2
    bluebo  
    OP
       170 天前
    @akin520 感谢暖贴 :)
    ChainLock
        3
    ChainLock  
       170 天前
    没明白,是做什么的
    bluebo
        4
    bluebo  
    OP
       170 天前
    @ChainLock 比如增量同步到 oracle,
    因为原表数据删除后,历史数据是不会存在表里面的, 但是 binlog 里面有记录, 我这个可以直接查 binlog 记录到 cdc 表中,这样历史记录也能查出来。 这样可以根据历史记录可以封装成 sql 到 oracle 执行, 实现增量同步

    row = select * from cdc_table where gitd> xxx and __tm > xxx ;
    switch __op
    {
    case 0:
    delete from dest_table where colx = row[x][x];
    case 1:
    insert into dest_table values row[x][x];
    case 2
    update set colx = row[x+1][x] where colx = row[x][x];
    }
    wenxueywx
        5
    wenxueywx  
       170 天前
    有用
    可以用来查询数据的历史版本、变更记录;是查问题的好帮手。
    有几个疑问?
    1 、 只能读取本地 mysql 的 binlog ?还是可以远程读
    2 、 是否支持只过滤某些表(黑白名单)?
    youngPacce
        6
    youngPacce  
       170 天前
    bluebo
        7
    bluebo  
    OP
       170 天前
    @wenxueywx
    目前只能读本地 binlog
    对于表的过滤, 我这边是一张 cdc 表对应一个 mysql 的表, 并不是所有表都会采集到一张 cdc 表,在创建 cdc 表时, 表名 为 xxx_cdc ,xxx 为具体要捕获的 mysql 表
    wenxueywx
        8
    wenxueywx  
       170 天前
    @bluebo 直接订阅 binlog 不行吗,去查 mysql 的表来封装 sql 不是多此一举?
    bluebo
        9
    bluebo  
    OP
       170 天前
    @wenxueywx 其他类型的数据库同步,并不是单指 mysql->mysql
    bluebo
        10
    bluebo  
    OP
       170 天前
    @youngPacce 是的,这种都大同小异, 只不过我是直接把捕获的数据重新写回 myql 了, 当作了 mysql 的记录集
    wenxueywx
        11
    wenxueywx  
       170 天前
    想问问是怎么想到这么做的,初衷是为了解决什么问题?
    cheng6563
        12
    cheng6563  
       170 天前
    看起来挺有用的,但如果不是独立部署而是 mysql 插件的话,感觉用起来会很难...
    bluebo
        13
    bluebo  
    OP
       170 天前
    @wenxueywx 工作原因接触过这部分代码, 然后写着玩了
    bluebo
        14
    bluebo  
    OP
       170 天前
    @cheng6563 难用不至于,就一个 so 文件, 主要还是鸡肋, 没有后续的想法
    RedisMasterNode
        15
    RedisMasterNode  
       170 天前
    觉得不太可能推广出去,因为 cdc 的工具有很多,并且都有各自的特色 + 不小的社区:
    - https://github.com/alibaba/canal
    - https://github.com/debezium/debezium
    - https://github.com/apache/flink-cdc
    - https://github.com/zendesk/maxwell

    所以楼主开发的工具和它们比起来有什么区别呢?

    PS:不是说钻研不好,只是钻研之后造轮子一个重要的原因应该是:现有工具不好用、不适合。不过从帖子描述看似乎不是很明显。
    bluebo
        16
    bluebo  
    OP
       170 天前
    @RedisMasterNode 倒是没想着往 cdc 走,要做 cdc 差的太多太多了。只是去年的练手项目, 直接用的 mysql 源码 自己加的估计就 2000 来行。只是想着有没有往小工具之类的发展形式
    changdy
        17
    changdy  
       169 天前
    15l 列举的比较相信.. 变更工具太多了.
    wenxueywx
        18
    wenxueywx  
       169 天前
    可以改一下
    wenxueywx
        19
    wenxueywx  
       169 天前
    有个想法可以参考:可以做成一个可以查询一定范围内任意时间点的历史数据的插件引擎(假设叫 binlogdb )
    1 、当使用 binlogdb 引擎创建表时会自动创建一个__optime 隐藏字段;
    2 、远程读多个 mysql server 的 binlog ,如果本地有同名的表,就将数据带上变更的时间写入该表
    3 、引入会话变量 optime ,使用 sql 查询表时默认加上 optime 字段,如果 optime 为空,则读取最新数据,不为空则读取__optime<=optime 的最新一条数据。
    4 、 设置一个淘汰机制
    bluebo
        20
    bluebo  
    OP
       169 天前
    @wenxueywx 会话变量 optime? 是不是就是刚连接上来的时间戳? __optime 就是数据变更时间戳把, 我那里是有一个__tm 的, 这个字段就是数据操作记录的变更时间戳,
    我感觉我这玩意的优势就是内置到数据库了, 可以直接用 sql 去过滤不需要的记录, 而且根据 gtid 去拿的数据的話 会很快。
    zhenjiachen
        21
    zhenjiachen  
       169 天前
    我们直接用 flink cdc ,mysql ,postgresql ,sqlserver 都支持。
    wenxueywx
        22
    wenxueywx  
       169 天前
    @bluebo 是的,__optime 就是数据变更时间__tm ;
    优势就是实现了 mysql 引擎的接口可以内置到 mysql 中使用,可以对接 mysql 生态。
    然后用户使用 gtid 去拿数据有点不符合操作习惯,你还得先知道 gtid ;使用时间就比较正常了。正常操作你只需设置一下时间,再用原来的 sql 直接执行就行,也基本没有增加使用负担。
    lvlongxiang199
        23
    lvlongxiang199  
       169 天前
    MySQL 中的表发生 DDL 你是咋处理的 ? MySQL8 之前的 binlog 里头没列名, binlog 中元素对应的表结构可能跟当前 MySQL 那边的表结构不一样
    bluebo
        24
    bluebo  
    OP
       169 天前
    @lvlongxiang199 DDL ,我没捕获, 但是 DDL 应该是对系统表做了增删改的操作,需要捕获系统表,而且不同版本的 mysql 不知道系统表有没有变化。
    bluebo
        25
    bluebo  
    OP
       169 天前
    @wenxueywx gtid 确实不直观,但是比__tm 更精准些。想想能不能直接在 mysql 上操作其他数据库(CRUD)。 应该也能实现,体量太大了
    bluebo
        26
    bluebo  
    OP
       169 天前
    @zhenjiachen 暂时只是做了捕获和展示的动作, 数据落地应该不会接着做了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3412 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 97ms · UTC 11:32 · PVG 19:32 · LAX 03:32 · JFK 06:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.