{"record":{"id":"fc9c6189644d08fc","repo":"MyCATApache/Mycat-Server","slug":"schema-schemal-table-table-sql-rrs-getstat","errorCode":null,"errorMessage":"schema:${schemal},table:${table},sql:${rrs.getStatement()} is not allowed,because table is migrate switching,please wait for a moment","messagePattern":"schema:(.+?),table:(.+?),sql:(.+?) is not allowed,because table is migrate switching,please wait for a moment","errorType":"exception","errorClass":"SQLNonTransientException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/route/RouteService.java","lineNumber":162,"sourceCode":"\t\tif (rrs != null && sqlType == ServerParse.SELECT && rrs.isCacheAble()) {\n\t\t\tsqlRouteCache.putIfAbsent(cacheKey, rrs);\n\t\t}\n\t\tcheckMigrateRule(schema.getName(),rrs,sqlType);\n\t\treturn rrs;\n\t}\n\n\t //数据迁移的切换准备阶段，需要拒绝写操作和所有的跨多节点写操作\n\t\tprivate   void checkMigrateRule(String schemal,RouteResultset rrs,int sqlType ) throws SQLNonTransientException {\n\t\tif(rrs!=null&&rrs.getTables()!=null){\n\t\t\tboolean isUpdate=isUpdateSql(sqlType);\n\t\t\tif(!isUpdate)return;\n\t\t\tConcurrentMap<String,List<PartitionByCRC32PreSlot.Range>> tableRules= RouteCheckRule.migrateRuleMap.get(schemal.toUpperCase()) ;\n\t\t\tif(tableRules!=null){\n\t\t\tfor (String table : rrs.getTables()) {\n\t\t\t\tList<PartitionByCRC32PreSlot.Range> rangeList= tableRules.get(table.toUpperCase()) ;\n\t\t\t\tif(rangeList!=null&&!rangeList.isEmpty()){\n\t\t\t\t\tif(rrs.getNodes().length>1&&isUpdate){\n\t\t\t\t\t\tthrow new   SQLNonTransientException (\"schema:\"+schemal+\",table:\"+table+\",sql:\"+rrs.getStatement()+\" is not allowed,because table is migrate switching,please wait for a moment\");\n\t\t\t\t\t}\n\t\t\t\t\tfor (PartitionByCRC32PreSlot.Range range : rangeList) {\n\t\t\t\t\t\tRouteResultsetNode[] routeResultsetNodes=\trrs.getNodes();\n\t\t\t\t\t\tfor (RouteResultsetNode routeResultsetNode : routeResultsetNodes) {\n\t\t\t\t\t\t\tint slot=routeResultsetNode.getSlot();\n\t\t\t\t\t\t\tif(isUpdate&&slot>=range.start&&slot<=range.end){\n\t\t\t\t\t\t\t\tthrow new   SQLNonTransientException (\"schema:\"+schemal+\",table:\"+table+\",sql:\"+rrs.getStatement()+\" is not allowed,because table is migrate switching,please wait for a moment\");\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/route/RouteService.java#L144-L180","documentation":"RouteService.checkMigrateRule throws SQLNonTransientException when a multi-node UPDATE targets a table that is currently in crc32slot data migration (switching). During migration, an update spanning more than one routed node could write to nodes whose slot ranges are being re-homed, so the write is rejected until migration completes.","triggerScenarios":"route() -> checkMigrateRule finds the table in RouteCheckRule.migrateRuleMap and the routed SQL is an UPDATE with rrs.getNodes().length > 1, i.e. the statement routes to multiple data nodes while a migration is in progress.","commonSituations":"Running DML through mycat while a crc32slot expansion/migration (schema data migration) is active; batch jobs issuing broad UPDATEs without slot-precise WHERE clauses during a scaling operation.","solutions":["Wait until the migration switch completes, then retry the statement.","Narrow the UPDATE so it routes to a single node (add a slot-determining predicate like the sharding column or explicit node route).","Check migration status files (datanode .properties / migrateRuleMap source) to confirm migration finished; clear stale migration rules if the migration is done.","Reschedule bulk update jobs outside migration windows."],"exampleFix":"// before\nUPDATE t SET x=1 WHERE id < 1000000; -- routes to many nodes\n// after\nUPDATE t SET x=1 WHERE id BETWEEN 1 AND 10000; -- repeat per sharding-key range, single slot","handlingStrategy":"retry","validationCode":"// check migration status before issuing multi-node updates\nboolean migrating = MigrationStatus.isActive(schema, table);\nif (migrating) { scheduleRetryAfterMigration(); }","typeGuard":null,"tryCatchPattern":"try {\n    execute(update);\n} catch (SQLNonTransientException e) {\n    if (e.getMessage().contains(\"migrate switching\")) {\n        retryWithBackoffAfterMigration();\n    } else { throw e; }\n}","preventionTips":["Schedule broad UPDATEs outside migration windows","Use slot/limit predicates so updates route to a single node","Track migration state before launching batch jobs"],"tags":["routing","migration","sql","update-blocked"],"backgroundTag":"unsupported-state-transition","analyzedSha":"65f8d8beb752f935752f2a0eec0ab017facab9ef","analyzedAt":"2026-09-11T00:12:21.696Z","contentChangedAt":"2026-09-11T00:12:21.696Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}