记一次Binlog解析的checksum解析异常

背景

一次客户现场发生binlog event的checksum的解析异常。

客观信息

异常

正常MySQL这个event checksum占用4字节,但是我们在解析event按照4字节去取的时候超过了LogBuffer的limit限制

1
2
3
4
5
6
7
8
9
2022-03-06 21:39:07.349 [destination = canal4aebs0c955t_INCREMENT , address = rm-bp1cayb56u4m70waa.mysql.rds.aliyuncs.com/10.10.3.84:3306 , EventParser] ERROR c.c.c.m.worker.reader.incre.RdsLocalBinlogEventParser - unknown exception in rds local binlog parser.
java.lang.IllegalArgumentException: limit excceed: 139698
at com.clougence.cloudcanal.ds.common.mysql.reader.binlog.LogBuffer.getUint32(LogBuffer.java:525)
at com.clougence.cloudcanal.ds.common.mysql.reader.binlog.event.LogHeader.processCheckSum(LogHeader.java:202)
at com.clougence.cloudcanal.ds.common.mysql.reader.binlog.event.LogHeader.<init>(LogHeader.java:196)
at com.clougence.cloudcanal.mysql.worker.reader.vendor.model.binlog.LogDecoder.decode(LogDecoder.java:66)
at com.clougence.cloudcanal.mysql.worker.reader.vendor.parse.conn.LocalBinLogConnection.dump(LocalBinLogConnection.java:259)
at com.clougence.cloudcanal.mysql.worker.reader.vendor.parse.AbstractEventParser$1.run(AbstractEventParser.java:284)
at java.lang.Thread.run(Thread.java:748)

复现&分析

根据用户提供的binlog文件,单独进行文件的解析。可以复现问题。主要原因是event的长度超过了buffer缓冲池的大小。fetch日志的时候,首次填充缓冲池的时候由于没有拿到event length,所有没对buffer容量是否扩容做判断。后续拿到event length超过buffer size的时候,取bytes解析的时候就会出错。
image.png

image.png

解决方案

知道本质原因后,解法自然也呼之欲出。主要两种方式:

  • 增大初始化的buffer size,先解决用户问题
  • 首次fetch的时候,试解析获取event length,然后判断是否需要直接做容量扩容