开发者社区> 问答> 正文

开启tsdb配置后,fastsql 解析 sql语句失败

环境信息

canal version:1.4 mysql version:MySQL5.7

问题描述

在源库中创建一个表,sql如下:

CREATE TABLE test ( id INT NOT NULL auto_increment, _enum enum ( 'a', 'b', 'c', 'd' ) CHARACTER SET binary DEFAULT 'a', PRIMARY KEY ( id ) USING BTREE ) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic

然后启动canal,在初始化阶段首先snapshot表结构,其中在dumpTableMeta函数中会将获取到的建表语句apply到内存中的repository,这一步出错了,报错如下: 2022-12-14 15:43:47.723 [destination = example , address = localhost/127.0.0.1:3306 , EventParser] WARN c.a.otter.canal.parse.inbound.mysql.tsdb.MemoryTableMeta - parse faield : CREATE TABLE test ( id int(11) NOT NULL AUTO_INCREMENT, _enum enum('a','b','c','d') CHARACTER SET binary DEFAULT 'a', PRIMARY KEY (id) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin ROW_FORMAT=DYNAMIC com.alibaba.fastsql.sql.parser.ParserException: pos 114, line 3, column 48, token BINARY at com.alibaba.fastsql.sql.dialect.mysql.parser.MySqlExprParser.parseColumn(MySqlExprParser.java:893) ~[fastsql-2.0.0_preview_973.jar:2.0.0_preview_973] at com.alibaba.fastsql.sql.dialect.mysql.parser.MySqlCreateTableParser.parseCreateTable(MySqlCreateTableParser.java:268) ~[fastsql-2.0.0_preview_973.jar:2.0.0_preview_973] at com.alibaba.fastsql.sql.dialect.mysql.parser.MySqlStatementParser.parseCreate(MySqlStatementParser.java:291) ~[fastsql-2.0.0_preview_973.jar:2.0.0_preview_973] at com.alibaba.fastsql.sql.parser.SQLStatementParser.parseStatementList(SQLStatementParser.java:231) ~[fastsql-2.0.0_preview_973.jar:2.0.0_preview_973] at com.alibaba.fastsql.sql.SQLUtils.parseStatements(SQLUtils.java:536) ~[fastsql-2.0.0_preview_973.jar:2.0.0_preview_973] at com.alibaba.fastsql.sql.repository.SchemaRepository.console(SchemaRepository.java:439) ~[fastsql-2.0.0_preview_973.jar:2.0.0_preview_973] at com.alibaba.otter.canal.parse.inbound.mysql.tsdb.MemoryTableMeta.apply(MemoryTableMeta.java:70) ~[classes/:na] at com.alibaba.otter.canal.parse.inbound.mysql.tsdb.DatabaseTableMeta.dumpTableMeta(DatabaseTableMeta.java:231) [classes/:na] at com.alibaba.otter.canal.parse.inbound.mysql.tsdb.DatabaseTableMeta.rollback(DatabaseTableMeta.java:177) [classes/:na] at com.alibaba.otter.canal.parse.inbound.mysql.AbstractMysqlEventParser.processTableMeta(AbstractMysqlEventParser.java:143) [classes/:na] at com.alibaba.otter.canal.parse.inbound.AbstractEventParser$3.run(AbstractEventParser.java:204) [classes/:na] at java.lang.Thread.run(Thread.java:748) [na:1.8.0-282]

实验了下,如果将_enum字段的字符集去掉或者改成utf8,sql如下: CREATE TABLE test ( id INT NOT NULL auto_increment, _enum enum ( 'a', 'b', 'c', 'd' ) CHARACTER SET utf8 DEFAULT 'a', PRIMARY KEY ( id ) USING BTREE ) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic

这样是没有问题的,正常的日志是这样的:

2022-12-14 15:46:08.448 [destination = example , address = localhost/127.0.0.1:3306 , EventParser] DEBUG java.sql.PreparedStatement - {pstm-100010} Parameters: [example, mysql-bin.000002, 796428, 1, 1671003933000, canal_test, canal_test, test2, CREATE TABLE test2 ( id INT NOT NULL auto_increment, _enum enum ( 'a', 'b', 'c', 'd' ) CHARACTER SET utf8 DEFAULT 'a', PRIMARY KEY ( id ) USING BTREE ) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic, CREATE, null] 2022-12-14 15:46:08.448 [destination = example , address = localhost/127.0.0.1:3306 , EventParser] DEBUG java.sql.PreparedStatement - {pstm-100010} Types: [java.lang.String, java.lang.String, java.lang.Long, java.lang.String, java.lang.Long, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, null] 2022-12-14 15:46:08.453 [destination = example , address = localhost/127.0.0.1:3306 , EventParser] DEBUG org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource

代码出错的地方:

MemoryTableMeta类中的apply方法, try { if (!StringUtils.startsWithIgnoreCase(StringUtils.trim(ddl), "flush") && !StringUtils.startsWithIgnoreCase(StringUtils.trim(ddl), "grant") && !StringUtils.startsWithIgnoreCase(StringUtils.trim(ddl), "revoke") && !StringUtils.startsWithIgnoreCase(StringUtils.trim(ddl), "create user") && !StringUtils.startsWithIgnoreCase(StringUtils.trim(ddl), "alter user") && !StringUtils.startsWithIgnoreCase(StringUtils.trim(ddl), "drop user")) { // 在这一步出错了 repository.console(ddl); } } catch (Throwable e) { logger.warn("parse faield : " + ddl, e); }

期待执行结果

Just put your stack trace here!

原提问者GitHub用户leoloel

展开
收起
白夜行fighting 2023-04-25 20:04:00 175 0
1 条回答
写回答
取消 提交回答
  • 升级版本1.1.7解决

    原回答者GitHub用户agapple

    2023-04-26 17:16:52
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
神龙云服务器产品及技术深度解析 立即下载
弹性创造价值:基于ECS的最佳性价比实践解析 立即下载
又快又稳:阿里云下一代虚拟交换机解析 立即下载

相关镜像