注册

达梦mysql模式,不适配seata

2025/09/16 388 8

为提高效率,提问时请提供以下信息,问题描述清晰可优先响应。
【DM版本】: 8 最新版
【操作系统】:win11
【CPU】: AMD
【问题描述】*:
达梦驱动版本:DmJdbcDriver18-8.1.3.140.jar
seata版本:1.8.0

由于业务系统是从mysql迁移到达梦的,因此达梦数据库安装时COMPATIBLE_MODE设置的是mysql,并且jdbcurl里也指定了parse_type参数为mysql:jdbc:dm://127.0.0.1:5237?SCHEMA=xxx&ServerOption={parse_type=MYSQL},
普通的查询没有问题,但是使用seata的AT模式全局事务的地方,会报语法分析出错:

2025-09-16 14:37:02,949 ERROR [http-nio-32000-exec-9] [i.s.r.d.sql.struct.cache.AbstractTableMetaCache] AbstractTableMetaCache.java:71 - get table meta of the table `sys_user` error: 第 1 行, 第 957 列[)]附近出现错误: 
语法分析出错
dm.jdbc.driver.DMException: 第 1 行, 第 957 列[)]附近出现错误: 
语法分析出错
	at dm.jdbc.driver.DBError.throwException(SourceFile:738)
	at dm.jdbc.a.a.y.r(SourceFile:623)
	at dm.jdbc.a.a.f.r(SourceFile:138)
	at dm.jdbc.a.a.y.z(SourceFile:555)
	at dm.jdbc.a.a.y.L(SourceFile:536)
	at dm.jdbc.a.a.a(SourceFile:269)
	at dm.jdbc.a.a.a(SourceFile:813)
	at dm.jdbc.driver.DmdbStatement.do_executeQueryWithConst(SourceFile:806)
	at dm.jdbc.util.DriverUtil.executeQueryWithConst(SourceFile:649)
	at dm.jdbc.driver.DmdbDatabaseMetaData.do_getColumns(SourceFile:262)
	at dm.jdbc.driver.DmdbDatabaseMetaData.getColumns(SourceFile:4152)
	at io.seata.rm.datasource.sql.struct.cache.DmTableMetaCache.resultSetMetaToSchema(DmTableMetaCache.java:62)
	at io.seata.rm.datasource.sql.struct.cache.OracleTableMetaCache.fetchSchema(OracleTableMetaCache.java:68)
	at io.seata.rm.datasource.sql.struct.cache.AbstractTableMetaCache.lambda$getTableMeta$0(AbstractTableMetaCache.java:69)
	at com.github.benmanes.caffeine.cache.BoundedLocalCache.lambda$doComputeIfAbsent$14(BoundedLocalCache.java:2406)
	at java.base/java.util.concurrent.ConcurrentHashMap.compute(ConcurrentHashMap.java:1908)
	at com.github.benmanes.caffeine.cache.BoundedLocalCache.doComputeIfAbsent(BoundedLocalCache.java:2404)
	at com.github.benmanes.caffeine.cache.BoundedLocalCache.computeIfAbsent(BoundedLocalCache.java:2387)
	at com.github.benmanes.caffeine.cache.LocalCache.computeIfAbsent(LocalCache.java:108)
	at com.github.benmanes.caffeine.cache.LocalManualCache.get(LocalManualCache.java:62)
	at io.seata.rm.datasource.sql.struct.cache.AbstractTableMetaCache.getTableMeta(AbstractTableMetaCache.java:67)
	at io.seata.rm.datasource.exec.BaseTransactionalExecutor.getTableMeta(BaseTransactionalExecutor.java:309)
	at io.seata.rm.datasource.exec.BaseTransactionalExecutor.getTableMeta(BaseTransactionalExecutor.java:294)
	at io.seata.rm.datasource.exec.UpdateExecutor.beforeImage(UpdateExecutor.java:68)
	at io.seata.rm.datasource.exec.AbstractDMLBaseExecutor.executeAutoCommitFalse(AbstractDMLBaseExecutor.java:98)

跟踪了报错的代码,发现是达梦驱动生成的获取meta的sql语句报错了,原始sql:

/*DMJDBC*/ SELECT /*+ MAX_OPT_N_TABLES(5) */ DISTINCT NULL AS TABLE_CAT, SCHS.NAME AS TABLE_SCHEM, TABS.NAME AS TABLE_NAME, COLS.NAME AS COLUMN_NAME, CASE COLS.TYPE$ WHEN 'BOOL' THEN 16 WHEN 'BOOLEAN' THEN 16 WHEN 'BIT' THEN -7 WHEN 'NUMBER' THEN 3 WHEN 'NUMERIC' THEN 3 WHEN 'DEC' THEN 3 WHEN 'DECIMAL' THEN 3 WHEN 'INT' THEN 4 WHEN 'INTEGER' THEN 4 WHEN 'BIGINT' THEN -5 WHEN 'TINYINT' THEN -6 WHEN 'SMALLINT' THEN 5 WHEN 'FLOAT' THEN 6 WHEN 'DOUBLE' THEN 8 WHEN 'REAL' THEN 7 WHEN 'DOUBLE PRECISION' THEN 8 WHEN 'CHARACTER' THEN 1 WHEN 'VARCHAR' THEN 12 WHEN 'VARCHAR2' THEN 12 WHEN 'TEXT' THEN -1 WHEN 'LONGVARCHAR' THEN -1 WHEN 'CLOB' THEN 2005 WHEN 'BYTE' THEN -6 WHEN 'BINARY' THEN -2 WHEN 'VARBINARY' THEN -3 WHEN 'LONGVARBINARY' THEN -4 WHEN 'BLOB' THEN 2004 WHEN 'IMAGE' THEN -4 WHEN 'TIMESTAMP' THEN 93 WHEN 'DATE' THEN 91 WHEN 'TIME' THEN 92 WHEN 'DATETIME' THEN 93 WHEN 'CURSOR' THEN -10 ELSE SF_GET_DATA_TYPE(COLS.TYPE$, CAST(COLS.SCALE AS INT), 3) END AS DATA_TYPE,CASE INSTR(COLS.TYPE$,'CLASS',1,1) WHEN 0 THEN COLS.TYPE$ ELSE SF_GET_CLASS_NAME(COLS.TYPE$) END AS TYPE_NAME,CASE SF_GET_COLUMN_SIZE(COLS.TYPE$, CAST (COLS.LENGTH$ AS INT), CAST (COLS.SCALE AS INT)) WHEN -2 THEN NULL ELSE SF_GET_COLUMN_SIZE(COLS.TYPE$, CAST (COLS.LENGTH$ AS INT), CAST (COLS.SCALE AS INT)) END AS COLUMN_SIZE,CASE SF_GET_BUFFER_LEN(COLS.TYPE$, CAST (COLS.LENGTH$ AS INT), CAST (COLS.SCALE AS INT)) WHEN -2 THEN NULL ELSE SF_GET_BUFFER_LEN(COLS.TYPE$, CAST (COLS.LENGTH$ AS INT), CAST (COLS.SCALE AS INT)) END AS BUFFER_LENGTH,CASE SF_GET_DECIMAL_DIGITS(COLS.TYPE$, CAST (COLS.SCALE AS INT)) WHEN -2 THEN NULL ELSE SF_GET_DECIMAL_DIGITS(COLS.TYPE$, CAST (COLS.SCALE AS INT)) END AS DECIMAL_DIGITS,10 AS NUM_PREC_RADIX,CASE COLS.NULLABLE$ WHEN 'Y' THEN 1 ELSE 0 END AS NULLABLE,(SELECT COMMENT$ FROM SYS.SYSCOLUMNCOMMENTS WHERE SCHNAME=SCHS.NAME AND TVNAME=TABS.NAME AND COLNAME=COLS.NAME) AS REMARKS,COLS.DEFVAL AS COLUMN_DEF,0 AS SQL_DATA_TYPE,0 AS SQL_DATETIME_SUB,CASE SF_GET_OCT_LENGTH(COLS.TYPE$, CAST (COLS.LENGTH$ AS INT), CAST (COLS.SCALE AS INT)) WHEN -2 THEN NULL ELSE SF_GET_OCT_LENGTH(COLS.TYPE$, CAST (COLS.LENGTH$ AS INT), CAST (COLS.SCALE AS INT)) END AS CHAR_OCTET_LENGTH,COLS.COLID + 1 AS ORDINAL_POSITION,CASE COLS.NULLABLE$ WHEN 'Y' THEN 'YES' ELSE 'NO' END AS IS_NULLABLE,NULL AS SCOPE_CATALOG,NULL AS SCOPE_SCHEMA,NULL AS SCOPE_TABLE,0 AS SOURCE_DATA_TYPE, CASE COLS.INFO2 & 0x01 WHEN 1 THEN 'YES' ELSE 'NO' END AS IS_AUTOINCREMENT, CASE (select INFO1 & 0x01 from SYS.SYSCOLINFOS where ID = COLS.ID and COLID = COLS.COLID) WHEN 1 THEN 'YES' ELSE 'NO' END AS IS_GENERATEDCOLUMN FROM (SELECT ID, PID, NAME FROM SYS.SYSOBJECTS WHERE TYPE$ = 'SCH' AND NAME LIKE ?  ESCAPE '!' ) SCHS, (SELECT ID, SCHID, NAME FROM SYS.SYSOBJECTS WHERE TYPE$ = 'SCHOBJ' AND SUBTYPE$ IN ('UTAB', 'STAB', 'VIEW')AND NAME LIKE ?  ESCAPE '!' )TABS, (SELECT A.NAME AS NAME, A.ID AS ID,A.COLID AS COLID, CASE WHEN B.INFO1 IS NULL OR ((B.INFO1>>2) & 0x01)=0 THEN A.TYPE$ WHEN (B.INFO2 & 0xFF) = 0 THEN 'NUMBER' ELSE 'FLOAT' END AS TYPE$, CASE WHEN B.INFO1 IS NULL OR ((B.INFO1>>2) & 0x01)=0 THEN A.LENGTH$ ELSE (B.INFO2 & 0xFF) END AS LENGTH$,CASE WHEN B.INFO1 IS NULL OR ((B.INFO1>>2) & 0x01)=0 THEN A.SCALE WHEN (B.INFO2 & 0xFF) = 0 THEN 0 ELSE 129 END AS SCALE,A.NULLABLE$ AS NULLABLE$,A.DEFVAL AS DEFVAL,A.INFO1 AS INFO1,A.INFO2 AS INFO2 FROM SYS.SYSCOLUMNS A LEFT JOIN SYS.SYSCOLINFOS B ON A.ID = B.ID AND A.COLID = B.COLID )COLS WHERE TABS.ID = COLS.ID AND SCHS.ID = TABS.SCHID  ORDER BY TABLE_SCHEM ASC,TABLE_NAME ASC,ORDINAL_POSITION ASC;

驱动代码:
image.png
好像是这个写法CAST(field as INT),当parse_type=mysql时,会报错。
并且这是驱动的错误,不是seata的问题。

请问有没有什么解决方案?

方案1:想办法改写并替换掉驱动里的MetaSQL文件
方案2:通过拦截器之类的,在sql发出前进行拦截并改写
方案3:指定这个sql的parse_type为oracle,其他的还是mysql
以上3种方案只是我的一个想法,但都不知道怎么做,也许不太可行。

回答 0
暂无回答
扫一扫
联系客服