环境信息
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
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。