
MySQL 接收到 SQL 后,第一步是词法分析(Lexical Analysis)
MySQL 并不是直接“看懂”你写的 SELECT * FROM user WHERE id = 1,而是先把它切成一个个有含义的单元,比如 SELECT、*、FROM、user、WHERE、id、=、1。这个切分过程由 lex_token() 函数驱动,底层基于 sql/lex.h 和 sql/sql_lex.cc 中的词法规则。
常见错误现象:ERROR 1064 (42000): You have an error in your SQL syntax 往往就卡在这步——比如写成 SELECt(拼错)或 SELECT * FROM user where id==1(多了一个 =),词法分析器无法识别出合法 token,直接报错,根本不会进后续流程。
- 词法分析不校验表是否存在、字段是否合法,只管“能不能切开”
- 大小写敏感性取决于系统变量
lower_case_table_names,但关键字(如SELECT)始终不区分大小写 - 注释(
--、/* */)在此阶段被剥离,不参与后续解析
紧接着是语法分析(Parsing),调用 MYSQLparse()
词法分析输出一串 token 后,MySQL 调用 MYSQLparse()(定义在 sql/sql_yacc.yy,由 Bison 生成)进行语法树构建。它依据预定义的语法规则(类似 BNF)判断这些 token 的组合是否符合 MySQL 支持的 SQL 语法结构。
例如:SELECT * FROM (SELECT 1) t 能过词法关,但 SELECT * FROM (SELECT 1) 缺少别名,在语法分析阶段就会失败(ERROR 1327 (42000): Undeclared variable 或类似提示,具体取决于版本)。
-
sql_yacc.yy是核心,修改它可扩展语法(极少见,且风险极高) - 语法分析阶段会初步绑定数据库名(如
db.table中的db),但不会查数据字典验证存在性 - 子查询、CTE、窗口函数等复杂结构都在这一步完成 AST(抽象语法树)节点构造
语法树生成后,立即进入语义分析(Semantic Analysis)和权限检查
AST 构建完成后,MySQL 进入 mysql_execute_command() 的早期分支,执行关键校验:
- 检查用户对涉及的数据库、表、列是否有
SELECT/INSERT等对应权限(查mysql.tables_priv等系统表) - 解析表名、字段名,将
user.id映射到实际的TABLE_LIST和Field对象,此时才真正访问数据字典(dict_table_t或TABLE_SHARE) - 检测字段歧义(如多表 JOIN 中未限定的
id)、不存在的列、聚合与非聚合混用等
典型报错:ERROR 1054 (42S22): Unknown column 'xxx' in 'field list' 或 ERROR 1142 (42000): SELECT command denied to user —— 都发生在这里,而非网络收包或词法阶段。
真正执行前的最后一步:查询优化(Optimization)
语义无误后,MySQL 调用优化器模块(make_join_statistics()、choose_plan() 等),生成执行计划(EXPLAIN 输出的内容)。它决定:
- 表的连接顺序(
JOINorder) - 用哪个索引(或是否全表扫描)
- 是否下推条件(
WHERE条件提前过滤) - 是否使用临时表、文件排序(
Using filesort)
注意:优化器不保证“最优”,只求“足够好”。统计信息不准(ANALYZE TABLE 没跑)、小表误判为大表、隐式类型转换导致索引失效,都会让这一步产出低效计划。这也是为什么 EXPLAIN 必须在真实环境下看,不能只信开发库结果。
SELECT * FROM orders o JOIN customers c ON o.cust_id = c.id WHERE o.status = 'shipped' AND c.country = 'CN';
这条语句从接收到返回,中间至少经过:socket 读取 → 字符串拆解(lex)→ token 序列生成 → 语法树构建(yacc)→ 表/字段解析 + 权限校验 → 优化器估算成本并选索引 → 执行器拉取数据 → 结果包返回。任何一环失败,都停在那一步,不会“跳过错误继续执行”。
最容易被忽略的是:词法和语法分析完全内存操作,不碰磁盘;而语义分析开始就要查系统表、打开表结构,这时候才真正产生 I/O 和锁等待。线上慢查询如果卡在“Sending data”之前,大概率是语义层或优化器在挣扎。










