oceanbase数据表由于使用Fulltext索引导致cloudcanal报错导致无法同步数据

【 使用环境 】生产环境
【 OB or 其他组件 】observer obproxy binlogserver ocp
【 使用版本 】ce 4.3.5.2-hf2
【问题描述】由于我们的某个表使用了全文索引。表结构如下:

CREATE TABLE `t_category` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL COMMENT '分类名称',
  `path` varchar(100) DEFAULT NULL COMMENT '路径,id以逗号连接,前后加逗号',
 
  PRIMARY KEY (`id`),
  FULLTEXT KEY `category_path` (`path`) WITH PARSER space PARSER_PROPERTIES=(min_token_size=3,max_token_size=84)
 
) AUTO_INCREMENT = 1000001 DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC 

在迁移到ob之前的mysql 可以工作的表是

CREATE TABLE `t_category` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL COMMENT '分类名称',
  `path` varchar(100) DEFAULT NULL COMMENT '路径,id以逗号连接,前后加逗号',
 
  PRIMARY KEY (`id`),
  FULLTEXT KEY `category_path` (`path`) 
 
)  ENGINE=InnoDB AUTO_INCREMENT=1000012 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC

【复现路径】cloudcanal 或者 canal 在接收到这张表的binlog event 会去 执行 show create table xxx.t_category, 在mysql的上 canal是兼容的,ob的 得到的ddl 包含了 “PARSER_PROPERTIES=(min_token_size=3,max_token_size=84)”

就报错了,整个日志如下:

WARN  c.c.c.m.worker.reader.vendor.parse.meta.MemoryTableMeta - parse failed : CREATE TABLE `t_category` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL COMMENT '分类名称',
  `path` varchar(100) DEFAULT NULL COMMENT '路径,id以逗号连接,前后加逗号',
  PRIMARY KEY (`id`),
  FULLTEXT KEY `category_path` (`path`) WITH PARSER space PARSER_PROPERTIES=(min_token_size=3,max_token_size=84)
) AUTO_INCREMENT = 1000001 DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMMENT = '分类'
com.alibaba.druid.sql.parser.ParserException: illegal name, pos 14xx, line 6, column 77, token =
	at com.alibaba.druid.sql.parser.SQLExprParser.name(SQLExprParser.java:2067)
	at com.alibaba.druid.sql.parser.SQLExprParser.parseDataType(SQLExprParser.java:3777)
	at com.alibaba.druid.sql.parser.SQLExprParser.parseDataType(SQLExprParser.java:3600)
	at com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser.parseColumn(MySqlExprParser.java:988)
	at com.alibaba.druid.sql.dialect.mysql.parser.MySqlCreateTableParser.parseCreateTable(MySqlCreateTableParser.java:272)
	at com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser.parseCreate(MySqlStatementParser.java:309)
	at com.alibaba.druid.sql.parser.SQLStatementParser.parseStatementList(SQLStatementParser.java:249)
	at com.alibaba.druid.sql.SQLUtils.parseStatements(SQLUtils.java:565)
	at com.alibaba.druid.sql.SQLUtils.parseStatements(SQLUtils.java:587)
	at com.alibaba.druid.sql.repository.SchemaRepository.console(SchemaRepository.java:445)
	at com.clougence.cloudcanal.mysql.worker.reader.vendor.parse.meta.MemoryTableMeta.apply(MemoryTableMeta.java:77)

binlog server 都是用ocp直接创建维护,默认也应该开了 _show_ddl_in_compat_mode

应该还是单独的druid 不兼容ob的这种非mysql标准的语法,请问有没有什么绕过方法 或者 后续优化路径?

类似的主题: oceanbase数据表由于使用多值索引导致Canal报错导致无法同步数据

2 个赞

非全局索引是正常的么

1 个赞

除了4.3.5.2 版本的 FULLTEXT KEY category_path (path) WITH PARSER space PARSER_PROPERTIES=(min_token_size=3,max_token_size=84)
生产上其他200多张表都正常的

1 个赞

_show_ddl_in_compat_mode麻烦确认下该参数是否开启了

1 个赞

WITH PARSER space PARSER_PROPERTIES=(min_token_size=3,max_token_size=84) 可能是OB特有的语法规则;MySQL 从 5.7 开始到 9.x 全文索引的语法图是

可以指定 WITH PARSER parser_name,但是不支持PARSER_PROPERTIES属性定义。
解决办法:SQLParse解析丢弃掉 WITH PARSER 后面的语法片段。粗糙点做法是用正则匹配过滤掉也可以。

1 个赞

ocp建的binlog server 默认应该开启了吧

该参数默认是关闭的

开启了 就能确认 PARSER_PROPERTIES=(min_token_size=3,max_token_size=84) 这个不会产生了,我搜索源代码没有找到

_show_ddl_in_compat_mode 这个我看有几个地方要去开启,

obproxy 或者 observer 可以获取

show variables like ‘%_show_ddl_in_compat_mode%’;

还有 这个 show proxyconfig like ‘%sql%’
init_sql 要 添加 set _show_ddl_in_compat_mode = 1;

3个地方有要设置?

加了 看着无效 还是 有 WITH PARSER space PARSER_PROPERTIES=(min_token_size=3,max_token_size=84) 输出

在obproxy设置一下

我问一下相关的同学 稍后回复你

目前cloudcanal 社区版用的 /data1/cloudcanal/sidecar/cloudcanal/bin/…/lib/druid-1.2.6.jar 这边版本的,我准备有时间去魔改绕过

就是在obproxy 2883 设置的

提供以下几种绕过方案和可能的优化路径:
1. 修改 CloudCanal 或 Canal 的代码 (推荐):

  • 忽略 PARSER_PROPERTIES 子句: 修改 CloudCanal 或 Canal 的代码,在解析 SHOW CREATE TABLE 结果时,使用正则表达式或者字符串处理方法,删除或忽略 PARSER_PROPERTIES 子句。这是一个相对安全的方案,不会影响 OceanBase 的表结构,只是修改了 DDL 解析器的行为。
  • 替换 SQL 解析器: 如果可能,尝试替换 CloudCanal 或 Canal 中使用的 SQL 解析器,选择一个更兼容 OceanBase 语法的解析器。例如,您可能需要研究是否存在更底层的sql解析器,看看能否兼容这种oceanbase的语法。
  • 定制化DDL Sync组件: 编写一个完全定制的DDL同步组件,可以完全掌控DDL解析和同步的逻辑,彻底解决兼容性问题。但这个方案工作量最大,如果时间和预算允许,也是一个不错的选择。

2. 修改 OceanBase 的配置 (谨慎):

  • 临时手段: 尝试修改会话级别的 _show_ddl_in_compat_mode 参数,看看是否能影响 SHOW CREATE TABLE 的结果,但这种方法可能不稳定。
SET _show_ddl_in_compat_mode = TRUE; -- 尝试设置为 TRUE
SHOW CREATE TABLE t_category;
SET _show_ddl_in_compat_mode = FALSE; -- 恢复原值

请注意: 修改 OceanBase 的配置可能影响系统稳定性,执行前务必进行充分测试并做好备份。

3. 修改 CloudCanal 或 Canal 的配置 (有限):

  • 过滤表: 如果只有少数表使用了全文索引,您可以尝试在 CloudCanal 或 Canal 的配置中,将这些表排除在 DDL 同步之外,手动创建这些表。然后仅仅同步数据。

4. 升级 CloudCanal 或 Canal 版本:

  • 检查 CloudCanal 或 Canal 的最新版本,看看是否已经修复了这个问题。新版本可能包含对 OceanBase 语法的支持。
1 个赞