mysql解析SQL语句是如何进行的_mysql语法解析过程

14次阅读

mysql的SQL解析发生在Server层第一阶段,仅做语法合法性判断并生成Parse Tree,不校验表结构或权限,核心由Bison基于sql_yacc.yy生成的LALR(1)分析器完成。

mysql解析SQL语句是如何进行的_mysql语法解析过程

MySQL 的 SQL 解析发生在哪个阶段

SQL 语句进入 MySQL 后,解析(parsing)是 Server 层的第一道处理环节,在执行器调用存储引擎前完成。它不涉及表结构校验或权限检查,只做语法合法性判断和初步结构化——也就是把字符串 select * FROM users WHERE id = 1 拆成「查询类型」「目标表」「条件表达式」等内部节点。

parse_yacc.yy 是核心,但你改不了它

MySQL 使用 gnu Bison 从 sql/sql_yacc.yy(旧版本)或 sql/parse_tree_nodes.h + 自动生成的 sql/sql_yacc.cc(8.0+)构建 LALR(1) 语法分析器。这意味着:

  • 所有合法 SQL 形式都由该文法定义,比如 INSERT ... ON DUPLICATE KEY UPDATE 能被识别,是因为文法规则里明确写了 insert_statement: INSERT ... on_duplicate_key_clause
  • 你无法通过配置或插件绕过或替换这个解析器;想支持新语法(如自定义函数关键字),必须修改 .yy 文件并重新编译 MySQL
  • 错误信息如 Error 1064 (42000): You have an error in your SQL syntax 就来自 Bison 的报错回调,位置通常精确到 Token 序号,但不包含列号

解析结果是 Parse Tree,不是 AST

MySQL 构建的是「解析树(Parse Tree)」,而非通用编译器意义上的抽象语法树(AST)。它的节点更贴近原始语法结构,例如:

SELECT a+b FROM t WHERE c > 10

会被拆为:

  • SELECT_LEX 节点含 item_list(存 a+b)、table_list(存 t)、where(存 c > 10
  • a+bItem_func_plus 实例,c > 10Item_func_gt,它们都继承Item,但此时尚未绑定字段类型或 NULL 属性
  • 这个树后续会传给语义分析器(如 SELECT_LEX::prepare())做字段名解析、类型推导、别名展开等——那才是真正的“查表”动作开始的地方

常见解析失败原因和定位方法

很多看似「语义错误」的问题其实在解析阶段就卡住了,比如:

  • 使用了保留字作别名却没加反引号:SELECT name AS order FROM torder 是保留字,Bison 规则中它被定义为关键字 token,直接匹配失败
  • 字符串未闭合:SELECT 'hello FROM t → 解析器一直等待下一个 ',直到缓冲区满或换行,报错位置常在末尾而非缺失处
  • jsON 字面量写成 {a: 1}(缺少引号)→ MySQL 8.0 只接受标准 json 格式 {"a": 1},否则解析器不认识 { 后跟标识符的组合
  • 客户端发送了多语句但未启用 CLIENT_MULTI_STATEMENTS 标志 → 即使 SQL 本身合法,MySQL Server 也会在解析第一句后丢弃剩余部分,不报错也不提示

调试时可开启 --debug=d,parser 启动 mysqld,它会在错误日志中输出 token 流和归约步骤,但输出极冗长,仅适合确认是否真的卡在某条规则上。

text=ZqhQzanResources