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

包含不是ER分片的表

Error message

%s包含不是ER分片的表

What it means

In the ER batch-insert routing flow, erFlag is set when the statement mix looks like an ER (global/ER-consistency) insert, but validation finds that the statement set includes tables that are not part of any ER relationship. Mycat cannot guarantee cross-shard consistency for such a mix, so it aborts with SQLNonTransientException '%s包含不是ER分片的表' ('%s contains tables that are not ER-sharded').

Solutions

  1. Separate statements touching non-ER tables from the ER batch and send them individually
  2. Declare all related tables in schema.xml as part of the ER relationship (childTable with parentKey/joinKey) if they belong together
  3. Remove the non-ER table from the batched statement set
  4. Review how erFlag is set — ensure only genuine ER inserts go through this routing path

Example fix

// before (one batch, mixed tables)
INSERT INTO orders(...) VALUES(...); INSERT INTO t_global(...) VALUES(...);
// after: send ER insert alone
INSERT INTO orders(...) VALUES(...);  // then separately
INSERT INTO t_global(...) VALUES(...);
Defensive patterns

Strategy: validation

Validate before calling

// Before batching statements, verify every target table is part of an ER relationship
for (String t : targetTables) {
    if (!erTables.contains(t)) throw new IllegalStateException("non-ER table " + t + " cannot be in an ER batch");
}

Try / catch

catch (SQLNonTransientException e) { if (e.getMessage().endsWith("包含不是ER分片的表")) { /* split batch by ER membership and resend */ } throw e; }

Prevention

When it happens

Trigger: routeByER returns true for erFlag, yet one or more tables in the multi-table/batch statement are ordinary (non-childTable, non-ER-group) tables in schema.xml; the check after the per-statement loop throws.

Common situations: Mixed multi-statement batches inserting into both ER and non-ER tables; schema.xml where only some joined tables are declared as childTable; renaming/adding a table to an ER group without updating all related tables; sending several INSERTs in one packet assuming Mycat handles them transactionally as ER.

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/300f0fc24ff214c1. Report an issue: GitHub.

Appendix: source

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

						if(processedInsert==false){
							RouteResultset executeRrs = RouterUtil.routeToSingleNode(rrs, result, origSQL);
							sc.getSession2().execute(executeRrs, ServerParse.INSERT);
						}

					}

					@Override
					public void onFailure(Throwable t) {
						StringBuilder s = new StringBuilder();
						LOGGER.warn(s.append(sc.getSession2()).append(origSQL).toString() +
								" err:" + t.getMessage());
						sc.writeErrMessage(ErrorCode.ER_PARSE_ERROR, t.getMessage() + " " + s.toString());
					}
				}, MycatServer.getInstance().
						getListeningExecutorService());

			} else if(erFlag) {
				throw new SQLNonTransientException(String.format("%s包含不是ER分片的表", origSQL));
			}
		}


		return erFlag;
	}

	/**
	 * 寻找joinKey的索引
	 *
	 * @param columns
	 * @param joinKey
	 * @return -1表示没找到,>=0表示找到了
	 */
	private static int getJoinKeyIndex(List<SQLExpr> columns, String joinKey) {
		for (int i = 0; i < columns.size(); i++) {
			String col = StringUtil.removeBackquote(columns.get(i).toString()).toUpperCase();
			if (col.equals(joinKey)) {

View on GitHub (pinned to 65f8d8beb7)