测试版本:canal 版本 1.0.24
Canal在实现该功能时,通过LogEventConvert.parseRowsEvent 解析event时抛出 TableIdNotFoundException, 但是parseRowsEvent 直接捕获了所有Exception,并重新抛出 CanalParseException,这样AbstractEventParser的parseThread 工作线程获取的一直都是Throwable的异常,无法感知到TableIdNotFoundException,导致陷入死循环;
修改LogEventConvert.parseRowsEvent 使其抛出TableIdNotFoundException后,下次循环线程会感知needTransactionPosition变量已经会true,进入findTransactionBeginPosition方法后,会调用seek方法,但seek方法只解析事务头/尾,那么当前的seek方法中实现的sink的event事件就解析不到(因为rowdata数据被过滤了),故reDump 一直都不会为true,从而也不会进入从头读取binlog的逻辑内,就又进入了主线程的死循环内。
PS: 个人简单分析,不知是否理解有误,抑或是findTransactionBeginPosition不是为了解决这个场景的?
修复建议1:
将LogEventConvert.parseRowsEvent 在catch CanalParseException前加个catch TableIdNotFoundException并将其抛出,让上层继续感知; 将MysqlEventParser.findTransactionBeginPosition方法中的第一个mysqlConnection.seek改为mysqlConnection.dump 即可解决这个BUG 修复建议2:因为MysqlEventParser.findTransactionBeginPosition只在needTransactionPosition为true时调用,故删除MysqlEventParser.findTransactionBeginPosition方法中的第一个mysqlConnection.seek逻辑,直接让其进入reDump逻辑内也可解决这个问题,减少一次dump请求;
原提问者GitHub用户wingerx
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。