{"record":{"id":"338d05cc6b642642","repo":"MyCATApache/Mycat-Server","slug":"you-have-an-error-in-your-sql-syntax-don-t-suppor","errorCode":null,"errorMessage":"You have an error in your SQL syntax, don't support lock multi tables!","messagePattern":"You have an error in your SQL syntax, don't support lock multi tables!","errorType":"exception","errorClass":"SQLNonTransientException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/route/parser/druid/impl/DruidLockTableParser.java","lineNumber":71,"sourceCode":"\t\t// 对于lock tables table1 write, table2 read类型的多表锁语句，DruidParser只能解析出table1，\n\t\t// 由于多表锁在分布式场景处理逻辑繁琐，且应用场景较少，因此在此处对这种锁表语句进行拦截。\n\t\t// 多表锁的语句在语义上会有\",\"，这里以此为判断依据\n\t\tString sql = rrs.getStatement();\n\t\tsql = sql.replaceAll(\"\\n\", \" \").replaceAll(\"\\t\", \" \");\n\t\tString[] stmts = SplitUtil.split(sql, ',', true);\n\t\t// 如果命令中存在\",\"，则按多表锁的语句来处理\n\t\tif (stmts.length > 1) {\n\t\t\tString tmpStmt = null;\n\t\t\tString tmpWords[] = null;\n\t\t\tfor (int i = 1; i < stmts.length; i ++) {\n\t\t\t\ttmpStmt = stmts[i];\n\t\t\t\ttmpWords = SplitUtil.split(tmpStmt, ' ', true);\n\t\t\t\tif (tmpWords.length==2 && (\"READ\".equalsIgnoreCase(tmpWords[1]) || \"WRITE\".equalsIgnoreCase(tmpWords[1]))) {\n\t\t\t\t\t// 如果符合多表锁的语法，则继续，并在最后提示不能多表锁！\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\t\t\t\t\t// 如果不符合多表锁的语法，则提示语法错误和不能多表锁！\n\t\t\t\t\tthrow new SQLNonTransientException(\"You have an error in your SQL syntax, don't support lock multi tables!\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tLOGGER.error(\"can't lock multi-table\");\n\t\t\tthrow new SQLNonTransientException(\"can't lock multi-table\");\n\t\t}\n\t}\n}\n","sourceCodeStart":53,"sourceCodeEnd":79,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/route/parser/druid/impl/DruidLockTableParser.java#L53-L79","documentation":"visitorParse rejects multi-table LOCK TABLES. When more than one table is locked, it splits the remaining statement text and, if an extra item does not match the strict '<table> READ|WRITE' two-token form, it throws SQLNonTransientException saying the SQL syntax is wrong and multi-table locks are unsupported.","triggerScenarios":"visitorParse on `LOCK TABLES a WRITE, b WRITE` (or similar) where a subsequent lock item's text doesn't split into exactly 2 space-separated words ending in READ or WRITE — e.g. extra whitespace tokens, AS aliases, or LOW_PRIORITY modifiers.","commonSituations":"Multi-table lock scripts from raw MySQL usage; aliasing (`LOCK TABLES t AS x READ`); driver-generated multi-table locks; statements with tabs or double spaces breaking the naive space split.","solutions":["Issue one LOCK TABLES statement per table instead of a comma-separated list","If you must keep multi-table syntax, keep each item exactly `table READ|WRITE` with single spaces and no aliases","Wrap the multi-table lock in a transaction with SELECT ... FOR UPDATE instead","Execute the lock directly on the datanode, bypassing MyCat"],"exampleFix":"// before\nLOCK TABLES t1 WRITE, t2 READ;\n// after\nLOCK TABLES t1 WRITE;\nLOCK TABLES t2 READ;","handlingStrategy":"validation","validationCode":"String[] items = sql.split(\",\"); if (items.length > 1) throw new IllegalArgumentException(\"multi-table LOCK TABLES not supported\");","typeGuard":null,"tryCatchPattern":"try { route(sql); } catch (SQLNonTransientException e) { if (e.getMessage().contains(\"don't support lock multi tables\")) { splitAndLockIndividually(sql); } else throw e; }","preventionTips":["Issue one LOCK TABLES per table","Avoid aliases and modifiers in lock statements routed via MyCat","Prefer SELECT ... FOR UPDATE inside transactions"],"tags":["sql","lock","unsupported","syntax"],"backgroundTag":"unsupported-operation","analyzedSha":"65f8d8beb752f935752f2a0eec0ab017facab9ef","analyzedAt":"2026-09-11T00:12:21.696Z","contentChangedAt":"2026-09-11T00:12:21.696Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}