You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@seata.apache.org by "fanfanyimeng (via GitHub)" <gi...@apache.org> on 2024/07/19 10:17:18 UTC

[I] get table meta error [incubator-seata]

fanfanyimeng opened a new issue, #6685:
URL: https://github.com/apache/incubator-seata/issues/6685

   <!-- Please do not use this issue template to report security vulnerabilities but refer to our [security policy](https://github.com/seata/seata/security/policy). -->
   
   - [ ] I have searched the [issues](https://github.com/seata/seata/issues) of this repository and believe that this is not a duplicate.
   
   ### Ⅰ. Issue Description
   seata 1.6.1(看了1.8和2.0的seata代码也有这个问题)
   seata 自动刷新 TableMetaCache 时报错 “get table meta error”
   
   ### Ⅱ. Describe what happened
   jdbc:mysql://x.x.x.x:3306/A
   数据库链接字串中配置的数据为A,此时有一个标注@GlobalTransaction的方法被调用,该方法操作了B数据库的table_1,即B.table_1,插入数据.
   这时 io.seata.rm.datasource.sql.struct.cache.AbstractTableMetaCache#getTableMeta 虽然正常运行 ,等到当io.seata.rm.datasource.sql.struct.cache.AbstractTableMetaCache#refresh 刷新时 就会报错了。
    “get table meta error”
   ```
   io.seata.rm.datasource.sql.struct.cache.AbstractTableMetaCache-tableMetaChecker_1_1-get table meta error:Table &#39;qmgr.qo_ord_anomalous&#39; doesn&#39;t exist-N/A-java.sql.SQLSyntaxErrorException: Table 'A.table_1' doesn't exist
   	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
   	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
   	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
   	at com.mysql.cj.jdbc.StatementImpl.executeQuery$original$sEQlPt7U(StatementImpl.java:1200)
   	at com.mysql.cj.jdbc.StatementImpl.executeQuery$original$sEQlPt7U$accessor$fo53R1GS(StatementImpl.java)
   	at com.mysql.cj.jdbc.StatementImpl$auxiliary$PTwarWz7.call(Unknown Source)
   	at org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstMethodsInter.intercept(InstMethodsInter.java:86)
   	at com.mysql.cj.jdbc.StatementImpl.executeQuery(StatementImpl.java)
   	at com.alibaba.druid.pool.DruidPooledStatement.executeQuery(DruidPooledStatement.java:296)
   	at io.seata.rm.datasource.sql.struct.cache.MysqlTableMetaCache.fetchSchema(MysqlTableMetaCache.java:82)
   	at io.seata.rm.datasource.sql.struct.cache.AbstractTableMetaCache.refresh(AbstractTableMetaCache.java:82)
   ```
   
   ### 最终排查因
   直接原因:
   1.4.2 代码是没有问题,是因为:client.rm.tableMetaCheckEnable 这个值默认为false,不会开启自动刷新cache
   1.6.x client.rm.tableMetaCheckEnable(io.seata.rm.datasource.DataSourceProxy#ENABLE_TABLE_META_CHECKER_ENABLE) 默认值就变成了 true 
   
   根本原因:
   io.seata.rm.datasource.sql.struct.cache.AbstractTableMetaCache#getTableMeta
      public TableMeta getTableMeta(final Connection connection, final String tableName, String resourceId) {
           if (StringUtils.isNullOrEmpty(tableName)) {
               throw new IllegalArgumentException("TableMeta cannot be fetched without tableName");
           }
   
           TableMeta tmeta;
           final String key = getCacheKey(connection, tableName, resourceId);
           tmeta = TABLE_META_CACHE.get(key, mappingFunction -> {
               try {
                   return fetchSchema(connection, tableName);
               } catch (SQLException e) {
                   LOGGER.error("get table meta of the table `{}` error: {}", tableName, e.getMessage(), e);
                   return null;
               }
           });
   
           if (tmeta == null) {
               throw new ShouldNeverHappenException(String.format("[xid:%s]get table meta failed," +
                   " please check whether the table `%s` exists.", RootContext.getXID(), tableName));
           }
          **tableName 参数为 B.table_1,而缓存中 tmeta.tableName的值变成了table_1**
           return tmeta;
       }
   
       public void refresh(final Connection connection, String resourceId) {
           ConcurrentMap<String, TableMeta> tableMetaMap = TABLE_META_CACHE.asMap();
           for (Map.Entry<String, TableMeta> entry : tableMetaMap.entrySet()) {
               String key = getCacheKey(connection, entry.getValue().getTableName(), resourceId);
               if (entry.getKey().equals(key)) {
                   try {
    **这里就取到了没有库前缀的tableName:table_1,在链接字符串 jdbc:mysql://x.x.x.x:3306/A 下访问 table_1 于是就报 A.table_1 不能存在 **
                       TableMeta tableMeta = fetchSchema(connection, entry.getValue().getTableName());
                       if (!tableMeta.equals(entry.getValue())) {
                           TABLE_META_CACHE.put(entry.getKey(), tableMeta);
                           LOGGER.info("table meta change was found, update table meta cache automatically.");
                       }
                   } catch (SQLException e) {
                       LOGGER.error("get table meta error:{}", e.getMessage(), e);
                   }
               }
           }
       }
   
   ### 最后
   可能seata没有考虑 在同一个程序中跨库访问,但是实际开发过程中由于各种原因会出现这种情况。
   在seata团队没有修复之前,如果有这个不太要紧的错误,看着太烦可以设置client.rm.tableMetaCheckEnable = false。
   
   希望可以帮助到一些人。
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org
For additional commands, e-mail: notifications-help@seata.apache.org


Re: [I] get table meta error [incubator-seata]

Posted by "funky-eyes (via GitHub)" <gi...@apache.org>.
funky-eyes commented on issue #6685:
URL: https://github.com/apache/incubator-seata/issues/6685#issuecomment-2239183803

   你可以尝试1.8或者2.0吗?这两个版本上是被动刷新,不是主动刷新,而2.2开始会恢复主动和被动两种方式
   Can you try 1.8 or 2.0? These two versions are passive refreshes, not active refreshes, and 2.2 will restore active and passive methods from now on.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org
For additional commands, e-mail: notifications-help@seata.apache.org


Re: [I] get table meta error [incubator-seata]

Posted by "GoodBoyCoder (via GitHub)" <gi...@apache.org>.
GoodBoyCoder commented on issue #6685:
URL: https://github.com/apache/incubator-seata/issues/6685#issuecomment-2266725213

   I will fix it!
   
   Tip: 由于表元数据缓存Key为单一表名,可能也存在跨库相同表名的情况下元数据获取错误的情况。
   Tip: Since the table metadata cache key is a single table name, metadata retrieval errors may occur when the same table name is used across databases.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org
For additional commands, e-mail: notifications-help@seata.apache.org


Re: [I] get table meta error [incubator-seata]

Posted by "funky-eyes (via GitHub)" <gi...@apache.org>.
funky-eyes commented on issue #6685:
URL: https://github.com/apache/incubator-seata/issues/6685#issuecomment-2254545084

   > > 看了1.8和2.0的seata代码也有这个问题
   > > 不过我这里倒是不要紧,我们避免跨库使用就好了。
   
   ok,我们将在社区邮件或会议上对这个问题进行相关讨论
   Ok, we will discuss this issue in a community email or meeting


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org
For additional commands, e-mail: notifications-help@seata.apache.org


Re: [I] get table meta error [incubator-seata]

Posted by "fanfanyimeng (via GitHub)" <gi...@apache.org>.
fanfanyimeng commented on issue #6685:
URL: https://github.com/apache/incubator-seata/issues/6685#issuecomment-2241924587

   > 看了1.8和2.0的seata代码也有这个问题
   不过我这里倒是不要紧,我们避免跨库使用就好了。
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org
For additional commands, e-mail: notifications-help@seata.apache.org


Re: [I] get table meta error [incubator-seata]

Posted by "funky-eyes (via GitHub)" <gi...@apache.org>.
funky-eyes closed issue #6685: get table meta error
URL: https://github.com/apache/incubator-seata/issues/6685


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org
For additional commands, e-mail: notifications-help@seata.apache.org