MyCATApache/Mycat-Server · error · java.sql.SQLNonTransientException

can't suport district table

Error message

can't suport district table  ${tableName} schema:${schema.getName()} for mutiple dataNode ${dataNodes}

What it means

Thrown when a district (dist) table is configured with more than one dataNode; dist-table routing requires the table to live on exactly one datanode because individual dist sub-tables are addressed by the sharding algorithm instead.

Solutions

  1. Set the dist table's dataNode in schema.xml to exactly one datanode
  2. Distribute sub-tables via the distTables naming pattern and the sharding algorithm's calculate() index instead of multiple dataNodes
  3. Reload configuration after the change

Example fix

// before (schema.xml)
<table name="log" dataNode="dn1,dn2" distTables="log_$0-9"/>
// after
<table name="log" dataNode="dn1" distTables="log_$0-9"/>
Defensive patterns

Strategy: validation

Validate before calling

TableConfig tc = schema.getTables().get(tableName.toUpperCase());
if (tc != null && tc.getDataNodes().size() > 1) throw new IllegalArgumentException("dist table must have one dataNode: " + tableName);

Try / catch

try { rrs = route(...); } catch (SQLNonTransientException e) { if (e.getMessage().contains("mutiple dataNode")) { LOG.warn("dist table dataNode must be single: " + e.getMessage()); } throw e; }

Prevention

When it happens

Trigger: routeToDistTableNode on a TableConfig whose getDataNodes().size() > 1 — i.e. schema.xml lists multiple dataNode entries for a dist table.

Common situations: Copy-pasted multi-node dataNode attribute on a dist table; misunderstanding that dist tables shard by sub-table name, not by datanode list; migration from a normal sharded table to dist tables without trimming dataNodes.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11). Data as JSON: /api/errors/73537e6003150e9e. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/io/mycat/route/util/RouterUtil.java:1454

            LOGGER.warn(msg);
            throw new SQLNonTransientException(msg);
        }
        if(tableConfig.isGlobalTable()){
            String msg = "can't suport district table  " + tableName + " schema:" + schema.getName() + " for global table ";
            LOGGER.warn(msg);
            throw new SQLNonTransientException(msg);
        }
        String partionCol = tableConfig.getPartitionColumn();
    //  String primaryKey = tableConfig.getPrimaryKey();
        //boolean isLoadData=false;
    
        Set<String> tablesRouteSet = new HashSet<String>();
    
        List<String> dataNodes = tableConfig.getDataNodes();
        if(dataNodes.size()>1){
            String msg = "can't suport district table  " + tableName + " schema:" + schema.getName() + " for mutiple dataNode " + dataNodes;
            LOGGER.warn(msg);
            throw new SQLNonTransientException(msg);
        }
        String dataNode = dataNodes.get(0);
    
        RouteResultsetNode[] nodes = null;
        //主键查找缓存暂时不实现
        if(tablesAndConditions.isEmpty()){
            List<String> subTables = tableConfig.getDistTables();
            tablesRouteSet.addAll(subTables);
    
            nodes = getNode(rrs, orgSql, tablesRouteSet, dataNode, false, tableName);
        } else {
            if (entry == null) {
                for(Map.Entry<String, Map<String, Set<ColumnRoutePair>>> entry1 : tablesAndConditions.entrySet()) {
                    //boolean isFoundPartitionValue = partionCol != null && entry.getValue().get(partionCol) != null;
                    setNodes(rrs, tableConfig, partionCol, tablesRouteSet, entry1);
                }
            } else {
                setNodes(rrs, tableConfig, partionCol, tablesRouteSet, entry);

View on GitHub (pinned to 65f8d8beb7)