这张图讲的是:客户端发送一条 SELECT 查询语句后,MySQL 内部是怎么一步步处理并返回结果的。

可以按图上的编号理解。
1. 连接器:先建立连接
客户端要执行 SQL,首先要和 MySQL 服务端建立连接。
比如你用 Java 程序连接 MySQL:
select * from user where id = 1;
SQL 不会直接去数据库文件里查,而是先通过网络协议发给 MySQL Server。
连接器主要做三件事:
例如:
mysql –u root –p
输入密码后,连接器会验证你是不是合法用户。
连接成功之后,这个连接会保持一段时间,后续 SQL 都通过这个连接发送。
2. 查询缓存:看看以前有没有查过
查询缓存的作用是:
如果之前执行过一模一样的 SQL,并且表数据没有变化,就直接返回缓存结果。
比如之前执行过:
select * from user where id = 1;
如果缓存中有结果,就不用继续解析、优化、执行了,直接返回。
但是这个模块在 MySQL 8.0 已经被删除。
原因是查询缓存很容易失效。
比如 user 表中任何一条数据发生变化:
update user set name = 'Tom' where id = 2;
哪怕你查的是 id = 1,这个表相关的查询缓存也可能被清空。
所以查询缓存看似提高性能,但在更新频繁的系统中反而维护成本很高。
现在面试里你可以这样说:
MySQL 8.0 之前有查询缓存,如果命中可以直接返回结果;但由于缓存失效频繁,实际收益不高,所以 MySQL 8.0 已经移除了查询缓存。
3. 解析器:检查 SQL 写得对不对
如果没有命中查询缓存,就进入解析器。
解析器主要做两步:
第一步:词法分析
把 SQL 拆成一个个单词,识别每个词是什么意思。
例如:
select name from user where id = 1;
MySQL 会识别出:
select 是关键字
name 是字段名
from 是关键字
user 是表名
where 是关键字
id 是字段名
1 是常量
第二步:语法分析
检查 SQL 语法是否符合 MySQL 规则。
比如你写成:
select from user where id = 1;
少了查询字段,语法分析就会报错。
如果语法正确,解析器会生成一个 语法树。
你可以把语法树理解成 MySQL 内部更容易理解的一种结构。
例如它会知道:
我要查 user 表
我要查 name 字段
查询条件是 id = 1
这是一个 SELECT 查询
4. 执行 SQL:预处理器、优化器、执行器
解析完成之后,SQL 还不会马上去磁盘查数据,而是进入执行 SQL 的流程。
这里分为三个阶段:
第一阶段:预处理器
预处理器主要检查两个问题。
1. 表是否存在
比如:
select * from student;
如果数据库中根本没有 student 表,就会在这个阶段报错。
2. 字段是否存在
比如:
select age from user;
如果 user 表中没有 age 字段,也会报错。
3. 展开 select *
例如:
select * from user;
假设 user 表有这些字段:
id, name, age, phone
那么 MySQL 内部会把 * 展开成:
select id, name, age, phone from user;
所以 select * 实际上不是直接查一个星号,而是查所有字段。
第二阶段:优化器
优化器的作用是:
决定这条 SQL 用什么方式执行成本最低。
比如有这样一条 SQL:
select * from user where id = 1 and name = 'Tom';
如果 id 上有索引,name 上也有索引,那么 MySQL 要决定:
是走 id 索引?
还是走 name 索引?
还是全表扫描?
优化器会根据统计信息估算成本,选择一个它认为最优的执行方案。
这个方案就叫 执行计划。
你可以把优化器理解为:
SQL 的路线规划器。
就像导航软件会选择一条预计最快的路线,优化器会选择一条预计成本最低的查询路径。
第三阶段:执行器
执行器拿到执行计划后,真正开始执行 SQL。
但是执行器本身不直接操作磁盘文件。
它会通过接口调用下面的 存储引擎。
比如 InnoDB、MyISAM 等。
图中有一句:
调用 API 接口
意思就是:
Server 层的执行器通过统一接口,让存储引擎去读数据。
例如执行:
select * from user where id = 1;
如果优化器决定走主键索引,那么执行器会告诉 InnoDB:
请根据主键 id = 1 帮我找这条记录
InnoDB 找到数据后返回给执行器。
执行器再把结果返回给连接器,最后返回给客户端。
5. 查询缓存记录:把结果放入缓存
如果是 MySQL 8.0 之前,并且开启了查询缓存,那么查询结果返回前,可能会把结果存入查询缓存。
这样下次执行完全一样的 SQL 时,可以直接从缓存返回。
不过再次强调:
MySQL 8.0 已经删除查询缓存,所以现在一般不重点考虑这个模块。
整体流程总结
一条 SQL 查询语句的执行过程可以总结成:
客户端发送 SQL
↓
连接器建立连接、校验身份、检查权限
↓
查询缓存,命中则直接返回
↓
解析器进行词法分析、语法分析,生成语法树
↓
预处理器检查表和字段是否存在,展开 select *
↓
优化器生成执行计划
↓
执行器根据执行计划调用存储引擎
↓
存储引擎读取数据
↓
执行器返回结果
↓
客户端收到结果
更简单地记:
连接器 → 查询缓存 → 解析器 → 预处理器 → 优化器 → 执行器 → 存储引擎
Server 层和存储引擎层的区别
图中上半部分是 Server 层,下半部分是 存储引擎层。
Server 层负责什么?
主要负责 MySQL 的通用功能:
连接管理
权限校验
SQL 解析
SQL 优化
SQL 执行
函数、存储过程、触发器、视图等
不管你用的是 InnoDB 还是 MyISAM,Server 层都一样。
存储引擎层负责什么?
存储引擎层负责真正的数据存储和读取。
比如:
数据怎么存
索引怎么组织
事务怎么实现
锁怎么加
数据页怎么读写
InnoDB 是最常用的存储引擎,它支持:
事务
行锁
MVCC
Redo Log
Undo Log
B+ 树索引
举个完整例子
执行:
select * from user where id = 10;
过程是:
面试时可以这样回答:
一条 SQL 查询语句首先经过连接器建立连接并校验权限,然后查看查询缓存,如果没有命中,就由解析器进行词法分析和语法分析生成语法树。接着进入预处理阶段,检查表和字段是否存在,并展开 select *。之后优化器根据成本选择最优执行计划,最后执行器按照执行计划调用存储引擎接口读取数据,并将结果返回给客户端。MySQL 8.0 已经删除了查询缓存模块。




