下面是我的实验步骤,发现除了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
在设计时,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来避免事务被截断。
说下我当时考虑的思路:
1、canal.instance.transaction.size,这个参数主要控制parser解析后,提交到event store时,如果要保证事务可见的一致性,设置的最大保证一致性的事务大小为1024. (举个例子:如果没有这一致性保护,你get频繁调用可能会拿到一次事务头,事务体数据,事务尾数据),事务的一致性写入是事务块读取的一个基础
2、目前get数据获取时,暂时没有考虑事务完整读取的机制,主要还是考虑业务需求,对于事务完整性不敏感. 要保证完整读取其实也不难.
原回答者GitHub用户agapple
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。