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

来源:这里教程网 时间:2026-02-28 20:40:13 作者:

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+b
Item_func_plus
实例,
c > 10
Item_func_gt
,它们都继承自
Item
,但此时尚未绑定字段类型或 NULL 属性
这个树后续会传给语义分析器(如
SELECT_LEX::prepare()
)做字段名解析、类型推导、别名展开等——那才是真正的“查表”动作开始的地方

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

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

使用了保留字作别名却没加反引号:
SELECT name AS order FROM t
order
是保留字,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 流和归约步骤,但输出极冗长,仅适合确认是否真的卡在某条规则上。

相关推荐