Canal 踩坑记录
之前用Canal 处理 mysql blog 日志。 记录了踩坑过程, 躺在笔记本里许久, 整理一下。
1、第一踩 获取不到binlog,无报错
我先使用本地Canal 链接了本地mysql数据库 , 版本mysql 8.0.13 过程和谐,链接正常,也能正常通信。 并转发kafka ,本地接收通信。
binlog最新日志文件:binlog.000011
后来,在将本地canal复制的数据库转成 dev环境数据库 mysql 5.7.31 后, 启动canal不报错, 但是不能接收到消息。
binlog最新日志文件:mysql-bin.001156
启动后最新日志:
2022-04-07 16:42:44.364 [destination = example , address = /127.0.0.1:3306 , EventParser] WARN c.a.o.c.p.inbound.mysql.rds.RdsBinlogEventParserProxy - ---> begin to find start position, it will be long time for reset or first position
2022-04-07 16:42:44.365 [destination = example , address = /127.0.0.1:3306 , EventParser] WARN c.a.o.c.p.inbound.mysql.rds.RdsBinlogEventParserProxy - prepare to find start position by switch ::1649314551000
调试许久,本以为用户权限问题, 查看过权限没问题。 并且根据用户账号链接数据库可以读取到binlog日志。
之后看到canal全量日志获取过程可能遇到的问题:canal.instance.master.journal.name不起作用问题。
发现这个问题需要消除 canal目前的状态才行,就是将 instance.properties 平级的 meta.dat 文件删除,这样canal才能从指定位置获取日志。
打开meta.dat 文件看了下, 里面记录了本地canal链接本地mysql的binlog同步进度, 导致链接dev环境过不去, 删除后,再次启动canal。可以正常从 dev mysql订阅消息。
2、第二踩 修改的库表已删除。
错误日志
1 2022-04-07 17:05:41.179 [destination = example , address = /127.0.0.1:3306 , EventParser] ERROR c.a.o.c.p.inbound.mysql.rds.RdsBinlogEventParserProxy - dump address /127.0.0.1:3306 has an error, retrying. caused by 2 com.alibaba.otter.canal.parse.exception.CanalParseException: com.alibaba.otter.canal.parse.exception.CanalParseException: com.alibaba.otter.canal.parse.exception.CanalParseException: fetch failed by table meta:`cygg`.`data_trace_zijinjiemi_zhuli` 3 Caused by: com.alibaba.otter.canal.parse.exception.CanalParseException: com.alibaba.otter.canal.parse.exception.CanalParseException: fetch failed by table meta:`cygg`.`data_trace_zijinjiemi_zhuli` 4 Caused by: com.alibaba.otter.canal.parse.exception.CanalParseException: fetch failed by table meta:`cygg`.`data_trace_zijinjiemi_zhuli` 5 Caused by: java.io.IOException: ErrorPacket [errorNumber=1142, fieldCount=-1, message=SHOW command denied to user 'binlog'@'127.0.0.1' for table 'data_trace_zijinjiemi_zhuli', sqlState=42000, sqlStateMarker=#] 6 with command: show create table `cygg`.`data_trace_zijinjiemi_zhuli` 7 at com.alibaba.otter.canal.parse.driver.mysql.MysqlQueryExecutor.query(MysqlQueryExecutor.java:61) ~[canal.parse.driver-1.1.6-SNAPSHOT.jar:na] 8 at com.alibaba.otter.canal.parse.inbound.mysql.MysqlConnection.query(MysqlConnection.java:106) ~[canal.parse-1.1.6-SNAPSHOT.jar:na] 9 at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.TableMetaCache.getTableMeta(TableMetaCache.java:186) ~[canal.parse-1.1.6-SNAPSHOT.jar:na] 10 at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.getTableMeta(LogEventConvert.java:975) ~[canal.parse-1.1.6-SNAPSHOT.jar:na] 11 at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.LogEventConvert.parseRowsEventForTableMeta(LogEventConvert.java:496) ~[canal.parse-1.1.6-SNAPSHOT.jar:na] 12 at com.alibaba.otter.canal.parse.inbound.mysql.MysqlMultiStageCoprocessor$SimpleParserStage.onEvent(MysqlMultiStageCoprocessor.java:280) ~[canal.parse-1.1.6-SNAPSHOT.jar:na] 13 at com.alibaba.otter.canal.parse.inbound.mysql.MysqlMultiStageCoprocessor$SimpleParserStage.onEvent(MysqlMultiStageCoprocessor.java:251) ~[canal.parse-1.1.6-SNAPSHOT.jar:na] 14 at com.lmax.disruptor.BatchEventProcessor.processEvents(BatchEventProcessor.java:168) ~[disruptor-3.4.2.jar:na] 15 at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:125) ~[disruptor-3.4.2.jar:na] 16 at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:1.8.0_281] 17 at java.util.concurrent.FutureTask.run(Unknown Source) ~[na:1.8.0_281] 18 at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:1.8.0_281] 19 at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:1.8.0_281] 20 at java.lang.Thread.run(Unknown Source) [na:1.8.0_281]
修改方式:
默认canal订阅了全库全表,
我这里业务只需要关注一个数据库就可以,
修改 instance.properties 配置文件的
1 # canal.instance.filter.regex=.*\\..* 2 # 修改为: 3 canal.instance.filter.regex=thsdb\..* # 只关注 thsdb 数据库的改动。相当于设置白名单 4 canal.instance.filter.black.regex=mysql\\.slave_.* # 这里设置黑名单
扩展知识:
canal.instance.filter.regex=.*\\..*
全库全表 |
.*\\..* |
.*\\..* |
指定库表 |
库名\..* |
thsdb\..* |
单表 |
库名.库表 |
thsdb.user |
多规则组合使用 |
库名1\..*,库名2.表名1,库名3.表名2 (逗号分隔) |
thsdb\..*,mysql.slow_log,sys.sys_config |
注意:这里修改后,对应 java 程序 connector.subscribe 配置也要修改
全库全表 |
.*\\..* |
connector.subscribe(".*\\..*") |
指定库表 |
库名\..* |
connector.subscribe("thsdb\\..*") |
单表 |
库名.库表 |
connector.subscribe("thsdb.user") |
多规则组合使用 |
库名1\..*,库名2.表名1,库名3.表名2 (逗号分隔) |
connector.subscribe("thsdb\\..*,mysql.slow_log,sys.sys_config") |
如果修改了 canal 的 instance文件,不要再客户端调用 connector.subscribe(".*\\..*"),相当于没配置。这里过滤根据 connector.subscribe("表达式")里的正则表达式过滤。
如果想在客户端调用 connector.subscribe(".*\\..*"),可以在 配置中设置 canal.instance.filter.black.regex=mysql\\.slave_.* 设置黑名单进行过滤。
3、第三踩 初次运行,表不存在,提示1146错误
不能保存,不能同步,怎么办。
canal 版本 1.1.6 ,
mysql 版本 5.7.4
【canal 版本canal.deployer-1.1.6-SNAPSHOT 在本地运行没有这个问题 】
这是最终改版的配置,conf/example/instance.properties 配置
1 # table regex 当前使用,监控 thsdb 库 2 canal.instance.filter.regex=thsdb\\..* 3 # table black regex 数据库解析表的黑名单, 暂时不需要 cygg库 4 canal.instance.filter.black.regex=mysql\\.slave_.*,cygg\\..*
但这个配置在最开始canal启动的时候,提示:Table 'thsdb.BASE TABLE' doesn't exist, 这个表确实不存在。
尝试了将配置改成默认的配置,还是不行,依旧是这个错误。
1 # table regex 当前使用,监控 thsdb 库 2 canal.instance.filter.regex=.*\\..* 3 # table black regex 数据库解析表的黑名单, 暂时不需要 cygg库 4 # canal.instance.filter.black.regex=mysql\\.slave_.*,cygg\\..*
也尝试了将这个错误跳过去,需要修改的是 canal.properties 配置 。没效果。
1 canal.instance.filter.table.error = true
最终尝试到一种方法
conf/example/instance.properties 配置
1 canal.instance.filter.regex=.\..
启动, 正常。
启动后生成 meta.bat 文件后。
再把配置修改为最终的
1 canal.instance.filter.regex=thsdb\\..*
终于启动成功。