MyCATApache/Mycat-Server · error · SQLNonTransientException

"Sharding column can't be updated " + tableName + "->" +…

Error message

"Sharding column can't be updated " + tableName + "->" + partitionColumn

What it means

Mycat forbids updating a table's sharding (partition) column: changing the shard key value could require moving the row to a different data node, which Mycat's UPDATE routing does not perform. In confirmShardColumnNotUpdated, if the SET item targets the partition column and shardColCanBeUpdated cannot prove the value stays routable, it throws SQLNonTransientException.

Solutions

  1. Remove the sharding column from the SET list; update it via DELETE + INSERT into the correct shard instead
  2. If the new value maps to the same data node, keep it but be aware shardColCanBeUpdated must be able to prove routability from the literal
  3. Redesign the schema so frequently-updated fields are not used as the partition column

Example fix

-- before
UPDATE orders SET customer_id = 456 WHERE order_id = 1001;
-- after
INSERT INTO orders (order_id, customer_id, ...) SELECT ... -- insert into target shard with new key
DELETE FROM orders WHERE order_id = 1001; -- remove from old shard
Defensive patterns

Strategy: validation

Validate before calling

if (updateSetColumns.contains(tableConfig.getPartitionColumn())) {
    throw new IllegalArgumentException("cannot update sharding column " + tableConfig.getPartitionColumn());
}

Try / catch

try { executeUpdate(sql); } catch (SQLNonTransientException e) { if (e.getMessage().startsWith("Sharding column can't be updated")) { doDeleteInsertInstead(); } else throw e; }

Prevention

When it happens

Trigger: An UPDATE SET clause assigning to the column configured as <partitionColumn> for that table (e.g. `UPDATE orders SET customer_id=456 WHERE ...`) when the new value is not provably in the same shard.

Common situations: Data-correction scripts changing the shard key; ETL jobs backfilling the partition column; apps reassigning ownership of a row (e.g. moving an order to another customer).

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/main/java/io/mycat/route/parser/druid/impl/DruidUpdateParser.java:234

    private void confirmShardColumnNotUpdated(SQLUpdateStatement update,SchemaConfig schema,String tableName,String partitionColumn,String joinKey,RouteResultset rrs) throws SQLNonTransientException {
        List<SQLUpdateSetItem> updateSetItem = update.getItems();
        if (updateSetItem != null && updateSetItem.size() > 0) {
            boolean hasParent = (schema.getTables().get(tableName).getParentTC() != null);
            for (SQLUpdateSetItem item : updateSetItem) {
                String column = StringUtil.removeBackquote(item.getColumn().toString().toUpperCase());
                //考虑别名,前面已经限制了update分片表的个数只能有一个,所以这里别名只能是分片表的
                if (column.contains(StringUtil.TABLE_COLUMN_SEPARATOR)) {
                    column = column.substring(column.indexOf(".") + 1).trim().toUpperCase();
                }
                if (partitionColumn != null && partitionColumn.equals(column)) {
                    boolean canUpdate;
                    canUpdate = ((update.getWhere() != null) && shardColCanBeUpdated(update.getWhere(),
                            partitionColumn, item.getValue(), false));

                    if (!canUpdate) {
                        String msg = "Sharding column can't be updated " + tableName + "->" + partitionColumn;
                        LOGGER.warn(msg);
                        throw new SQLNonTransientException(msg);
                    }
                }
                if (hasParent) {
                    if (column.equals(joinKey)) {
                        String msg = "Parent relevant column can't be updated " + tableName + "->" + joinKey;
                        LOGGER.warn(msg);
                        throw new SQLNonTransientException(msg);
                    }
                    rrs.setCacheAble(true);
                }
            }
        }
    }
}

View on GitHub (pinned to 65f8d8beb7)