开发者社区> 问答> 正文

关于事务被截断的疑问

下面是我的实验步骤,发现除了canal.instance.transaction.size参数可能导致事务被截断外,客户端batchsize的设置也会导致事务被截断,请问下,canla在设计的时候对事务完整性是一个什么样的考虑呢?只要保证能把数据同步给客户端,能记下ack,保证最终一致?

下面是我的实验。

1、创建一个测试用存储过程,过程代码如下:

DELIMITER // CREATE PROCEDURE loop_insert(IN count int) begin declare lp int; declare idvalue int; set lp=0; select max(id)+1 into idvalue from test; set autocommit=0; while lp<count do insert into test(id,name)values(idvalue,'test-'+idvalue); set idvalue=idvalue+1; set lp=lp+1; end while; commit; end; // DELIMITER;

测试“canal.instance.transaction.size” 将canal-server的“canal.instance.transaction.size”参数设置为1024(默认也是1024),canal-client(SimpleCanalClientTest)的batchsize设置为1024*5(要足够大) 依序启动mysql、canal-server和canal-client(在mysql执行操作之前,canal-client必须预先启动起来,否则事务截断的现象显示不出来)

在mysql端执行loop_insert,参数传1022,观察canal-client端:所有event会在一个batch中拿到 在mysql端执行loop_insert,参数传1023,观察canal-client端:会返回两个batch,第一个包含1024条event,第二个包含1条event

上面验证了参数"canal.instance.transaction.size"的作用,为了防止事务被截断需要把参数值设置的大一些

测试batchsize

3.1 场景一

将canal-server的参数设为ITEMSIZE(使用ITEMSIZE便于测试),将canal-client中的batchsize设置为2 启动mysql,启动canal-server,在mysql端执行loop_insert,参数传10,然后再启动canal-client 观察canal-client端:会返回6个batch,每个batch包含2条event,事务被截断

3.4 场景二

将canal-server的参数设为ITEMSIZE(使用ITEMSIZE便于测试),将canal-client中的batchsize设置为13 启动mysql,启动canal-server,在mysql端连续执行loop_insert两次,参数传10,然后再启动canal-client(必须上述操作完成后再启动client,保证3.4的真实性) 观察canal-client端:会返回两个batch,第一个batch13条event,第二个batch11条event,事务被截断

由此可见,除了需要考虑transaction size还需要考虑batch size,batchsize配置的比较小的话也可能截断事务,但是如果太大的话又会影响实时性,需要取一个折衷

注:再对2和3进行测试时,要保证相互隔离,即测试transaction.size的时候要保证batchsize的足够大,测试batchsize的时候亦然 canal.instance.transaction.size的目的是防止事务被截断,但是如果mysql的binlog-format是mixed类型,基本每个事件都会导致一次flush,canal.instance.transaction.size的设置就没什么意义了吧???

原提问者GitHub用户lulu2panpan

展开
收起
绿子直子 2023-05-09 16:05:40 104 0
2 条回答
写回答
取消 提交回答
  • 随心分享,欢迎友善交流讨论:)

    在设计时,canal确实考虑了事务的完整性。canal的工作原理是基于MySQL的binlog日志,通过解析binlog日志来获取MySQL数据库的增量数据。对于事务来说,binlog会记录事务的开始和结束,canal会在获取到事务开始的event时,将该事务的所有event都保存在一个缓存中,直到获取到该事务的结束event后再进行处理,确保了事务的完整性。因此,在canal的设计中,确实考虑了事务的完整性。

    对于你提到的事务被截断的问题,确实是需要考虑batch size的大小对事务的影响。batch size设置过小会导致事务被截断,但是如果设置过大又会影响实时性。因此,需要根据实际情况取一个合适的折衷。

    对于binlog-format是mixed类型,确实每个事件都会导致一次flush,这时候canal.instance.transaction.size的设置就没有意义了。因此,如果binlog-format是mixed类型,可以考虑关闭事务同步模式,即设置canal.instance.enableDdlSync=false来避免事务被截断。

    2023-05-10 11:05:47
    赞同 展开评论 打赏
  • 说下我当时考虑的思路:

    1、canal.instance.transaction.size,这个参数主要控制parser解析后,提交到event store时,如果要保证事务可见的一致性,设置的最大保证一致性的事务大小为1024. (举个例子:如果没有这一致性保护,你get频繁调用可能会拿到一次事务头,事务体数据,事务尾数据),事务的一致性写入是事务块读取的一个基础

    2、目前get数据获取时,暂时没有考虑事务完整读取的机制,主要还是考虑业务需求,对于事务完整性不敏感. 要保证完整读取其实也不难.

    原回答者GitHub用户agapple

    2023-05-10 11:05:46
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载