mysql接收到SQL后第一步做什么_mysql执行入口解析

9次阅读

mysql 接收到 SQL 后第一步做什么_mysql 执行入口解析

MySQL 接收到 SQL 后,第一步是词法分析(Lexical Analysis)

MySQL 并不是直接“看懂”你写的 SELECT * FROM user WHERE id = 1,而是先把它切成一个个有含义的单元,比如 SELECT*FROMuserWHEREid=1。这个切分过程由 lex_token() 函数驱动,底层基于 sql/lex.hsql/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_LISTField 对象,此时才真正访问数据字典(dict_table_tTABLE_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 输出的内容)。它决定:

  • 表的连接顺序(JOIN order)
  • 用哪个索引(或是否全表扫描)
  • 是否下推条件(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”之前,大概率是语义层或优化器在挣扎。

text=ZqhQzanResources