apache / incubator-seata

:fire: Seata is an easy-to-use, high-performance, open source distributed transaction solution.
https://seata.apache.org/
Apache License 2.0
25.38k stars 8.79k forks source link

springboot + shardingSphere5.0 + Dubbo2.7.x实现分库分表的情况下,集成 + seata1.4.2后,报出以下异常: Could not found any index in the table: xxx #4252

Open jlovej opened 2 years ago

jlovej commented 2 years ago

各位大神好,我在springboot + shardingSphere5.0 + Dubbo2.7.x实现分库分表(3个库,t_order分4张表)的情况下,集成 + seata1.4.2后,报出以下异常: Could not found any index in the table: xxx,查看了下源码,在io.seata.rm.datasource.sql.struct.cache.MysqlTableMetaCache#resultSetMetaToSchema方法中,会判断所有index是否为空,

try (ResultSet rsColumns = dbmd.getColumns(catalogName, schemaName, tableName, "%");
    ResultSet rsIndex = dbmd.getIndexInfo(catalogName, schemaName, tableName, false, true)) {
    while (rsIndex.next()) {
        String indexName = rsIndex.getString("INDEX_NAME");
        String colName = rsIndex.getString("COLUMN_NAME");
        ColumnMeta col = tm.getAllColumns().get(colName);

        if (tm.getAllIndexes().containsKey(indexName)) {
            IndexMeta index = tm.getAllIndexes().get(indexName);
            index.getValues().add(col);
        } else {
            IndexMeta index = new IndexMeta();
            index.setIndexName(indexName);
            index.setNonUnique(rsIndex.getBoolean("NON_UNIQUE"));
            index.setIndexQualifier(rsIndex.getString("INDEX_QUALIFIER"));
            index.setIndexName(rsIndex.getString("INDEX_NAME"));
            index.setType(rsIndex.getShort("TYPE"));
            index.setOrdinalPosition(rsIndex.getShort("ORDINAL_POSITION"));
            index.setAscOrDesc(rsIndex.getString("ASC_OR_DESC"));
            index.setCardinality(rsIndex.getInt("CARDINALITY"));
            index.getValues().add(col);
            if ("PRIMARY".equalsIgnoreCase(indexName)) {
                index.setIndextype(IndexType.PRIMARY);
            } else if (!index.isNonUnique()) {
                index.setIndextype(IndexType.UNIQUE);
            } else {
                index.setIndextype(IndexType.NORMAL);
            }
            tm.getAllIndexes().put(indexName, index);

        }
    }
    if (tm.getAllIndexes().isEmpty()) {
        throw new ShouldNeverHappenException("Could not found any index in the table: " + tableName);
    }
}
return tm;

【(tm.getAllIndexes().isEmpty()】这行条件成立就会抛出异常,请问此处的判断是什么用意,谢谢。 PS:表中都有主键

funky-eyes commented 2 years ago

分表后,debug看过此处的表名是什么吗? 主键也是会放到idnexes中

jlovej commented 2 years ago

分表后,debug看过此处的表名是什么吗? 主键也是会放到idnexes中

就是配置的逻辑表名t_order,主键使用的Sharding提供的SNOWFLAKE生成

funky-eyes commented 2 years ago

分表后,debug看过此处的表名是什么吗? 主键也是会放到idnexes中

就是配置的逻辑表名t_order,主键使用的Sharding提供的SNOWFLAKE生成

估计不是拿的实际表名查询导致的,这个问题可以反馈给sharding sphere社区一起看看

jlovej commented 2 years ago

分表后,debug看过此处的表名是什么吗? 主键也是会放到idnexes中

就是配置的逻辑表名t_order,主键使用的Sharding提供的SNOWFLAKE生成

估计不是拿的实际表名查询导致的,这个问题可以反馈给sharding sphere社区一起看看

好的,非常感谢

a1104321118 commented 2 years ago

各位大神好,我在springboot + shardingSphere5.0 + Dubbo2.7.x实现分库分表(3个库,t_order分4张表)的情况下,集成 + seata1.4.2后,报出以下异常: Could not found any index in the table: xxx,查看了下源码,在io.seata.rm.datasource.sql.struct.cache.MysqlTableMetaCache#resultSetMetaToSchema方法中,会判断所有index是否为空,

try (ResultSet rsColumns = dbmd.getColumns(catalogName, schemaName, tableName, "%");
  ResultSet rsIndex = dbmd.getIndexInfo(catalogName, schemaName, tableName, false, true)) {
  while (rsIndex.next()) {
      String indexName = rsIndex.getString("INDEX_NAME");
      String colName = rsIndex.getString("COLUMN_NAME");
      ColumnMeta col = tm.getAllColumns().get(colName);

      if (tm.getAllIndexes().containsKey(indexName)) {
          IndexMeta index = tm.getAllIndexes().get(indexName);
          index.getValues().add(col);
      } else {
          IndexMeta index = new IndexMeta();
          index.setIndexName(indexName);
          index.setNonUnique(rsIndex.getBoolean("NON_UNIQUE"));
          index.setIndexQualifier(rsIndex.getString("INDEX_QUALIFIER"));
          index.setIndexName(rsIndex.getString("INDEX_NAME"));
          index.setType(rsIndex.getShort("TYPE"));
          index.setOrdinalPosition(rsIndex.getShort("ORDINAL_POSITION"));
          index.setAscOrDesc(rsIndex.getString("ASC_OR_DESC"));
          index.setCardinality(rsIndex.getInt("CARDINALITY"));
          index.getValues().add(col);
          if ("PRIMARY".equalsIgnoreCase(indexName)) {
              index.setIndextype(IndexType.PRIMARY);
          } else if (!index.isNonUnique()) {
              index.setIndextype(IndexType.UNIQUE);
          } else {
              index.setIndextype(IndexType.NORMAL);
          }
          tm.getAllIndexes().put(indexName, index);

      }
  }
  if (tm.getAllIndexes().isEmpty()) {
      throw new ShouldNeverHappenException("Could not found any index in the table: " + tableName);
  }
}
return tm;

【(tm.getAllIndexes().isEmpty()】这行条件成立就会抛出异常,请问此处的判断是什么用意,谢谢。 PS:表中都有主键

我也遇到了这个问题,debug后发现,表面是 带了 引号,导致拿表结构的时候 tablename = '`t_order`', 去掉 号后正常 但是很奇怪,我的mysql 在5.6 的时候并没有遇到这个问题,升级到8.0 就出现了,代码没有任何改动,这块我还没来得及排查

smile942 commented 3 months ago

Hello, has this problem been solved,I also encountered this problem when using jdk17+spring-boot3.3.2 +spring-cloud2023.0.2+spring-cloud-alibaba 2023.0.1.0+shardingsphere-jdbc 5.5.0+sharding-transaction-base-seata-at 4.1.1.The same error io.seata.common.exception.ShouldNeverHappenException: Get table meta failed, please check whether the table t_order exists. is reported when implementing the distributed transaction of the microservice's repository and table through seata and shardingsphere

a1104321118 commented 3 months ago

您好  我已经收到你的邮件,谢谢!HR

linghengqian commented 3 months ago