MyCATApache/Mycat-Server · error · SQLNonTransientException

"can't find table define of " + table + " in schema:" +…

Error message

"can't find table define of " + table + " in schema:" + schema.getName()

What it means

Mycat's LOCK TABLES statement parser requires the locked table to be defined in the current logical schema's table configuration. When the parsed table name (uppercased) is not found in schema.getTables(), routing is impossible, so a SQLNonTransientException is thrown after logging a warning.

Solutions

  1. Add the table to schema.xml as a <table> entry in the schema being used, then reload the Mycat config
  2. Verify the table name in the LOCK TABLES statement exactly matches the configured table name (parser compares uppercased names)
  3. Route LOCK TABLES statements to a backend MySQL directly instead of through Mycat, as support is limited to WRITE/READ lock types on configured tables

Example fix

<!-- before: schema.xml missing table -->
<schema name="db1">
  <table name="t_user" dataNode="dn1"/>
</schema>
<!-- after: table locked by the app is declared -->
<schema name="db1">
  <table name="t_user" dataNode="dn1"/>
  <table name="t_lock" dataNode="dn1"/>
</schema>
Defensive patterns

Strategy: validation

Validate before calling

TableConfig tc = schema.getTables().get(tableName.toUpperCase());
if (tc == null) throw new IllegalStateException("table not in mycat schema.xml: " + tableName);

Type guard

if (schema != null && schema.getTables() != null && schema.getTables().containsKey(table.toUpperCase())) { ... }

Try / catch

try { route(...); } catch (SQLNonTransientException e) { if (e.getMessage().startsWith("can't find table define")) { fixSchemaConfig(); } else throw e; }

Prevention

When it happens

Trigger: Executing `LOCK TABLES <name> WRITE|READ` where <name> is not declared in the schema's <table> entries in schema.xml, or the statement's table name differs in case/format from the configured table name.

Common situations: Locking a table that exists only on the backend MySQL but was never added to Mycat's schema.xml; typos or case mismatches between the SQL table name and the configured logical table; running LOCK TABLES against Mycat-managed schemas without configuring the table as a sharding/global table.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at src/main/java/io/mycat/route/parser/druid/impl/DruidLockTableParser.java:33

import io.mycat.route.parser.druid.MycatSchemaStatVisitor;
import io.mycat.server.parser.ServerParse;
import io.mycat.util.SplitUtil;

/**
 * lock tables [table] [write|read]语句解析器
 * @author songdabin
 */
public class DruidLockTableParser extends DefaultDruidParser implements DruidParser {
	@Override
	public void statementParse(SchemaConfig schema, RouteResultset rrs, SQLStatement stmt)
			throws SQLNonTransientException {
		MySqlLockTableStatement lockTableStat = (MySqlLockTableStatement)stmt;
		String table = lockTableStat.getItems().get(0).getTableSource().toString().toUpperCase();
		TableConfig tableConfig = schema.getTables().get(table);
		if (tableConfig == null) {
			String msg = "can't find table define of " + table + " in schema:" + schema.getName();
			LOGGER.warn(msg);
			throw new SQLNonTransientException(msg);
		}
		LockType lockType = lockTableStat.getItems().get(0).getLockType();
		if (LockType.WRITE != lockType && LockType.READ != lockType) {
			String msg = "lock type must be write or read";
			LOGGER.warn(msg);
			throw new SQLNonTransientException(msg);
		}
		List<String> dataNodes = tableConfig.getDataNodes();
		RouteResultsetNode[] nodes = new RouteResultsetNode[dataNodes.size()];
		for (int i = 0; i < dataNodes.size(); i ++) {
			nodes[i] = new RouteResultsetNode(dataNodes.get(i), ServerParse.LOCK, stmt.toString());
		}
		rrs.setNodes(nodes);
		rrs.setFinishedRoute(true);
	}
	
	@Override
	public void visitorParse(SchemaConfig schema, RouteResultset rrs, SQLStatement stmt, MycatSchemaStatVisitor visitor)

View on GitHub (pinned to 65f8d8beb7)