
MySQL 查询语句可以分为 Server 层和存储引擎层。而 Server 层包括连接器、查询缓存、解析器、预处理器、优化器、执行器等,
最后 Server 层再通过 API 接口形式调用对应的存储引擎层提供的接口来执行增删改查操作。
如下图所示:
1、介绍
关于sql语句在执行过程中,可能会涉及到以下的组件来进行相互的调用。
1.1、组件介绍
组件及其作用,可参考:

1.2、Sql执行顺序
在 SQL 中,select语句的语法结构看似是按照关键字书写顺序执行的(如select ... from ... where ...),但实际执行顺序与语法顺序并不完全一致。
如下图所示:

注意:
在包含子查询的 SQL 中,子查询本身也是一个完整的select语句,其内部仍然遵循上述执行顺序。外部查询的执行顺序会以子查询的最终结果为输入继续执行。
为了更好地理解这个顺序,我们可以从“数据流”的角度思考:
如下图所示:

2、执行流程
一个完整的执行流程包括以下组件,连接器、缓存、解析器、优化器、执行器和存储引擎组成。
如下图所示:

2.1. 连接与认证
MySQL 服务端和客户端的通信方式采用的是半双工协议。
客户端连接:客户端通过协议(如 TCP/IP、Socket)与 MySQL 服务端建立连接。
认证:服务端验证用户身份(用户名、密码、权限)。如果验证失败,连接终止。
权限检查:确认用户是否有权限执行当前查询(如 SELECT 权限)。
常见的通信方式主要可以分为三种:单工,半双工,全双工。
单工:
通信的时候,数据只能单向传输。比如说遥控器,我们只能用遥控器来控制电视机,而不能用电视机来控制遥控器。
半双工:
通信的时候,数据可以双向传输,但是同一时间只能有一台服务器在发送数据,当 A 给 B 发送数据的时候,那么 B 就不能给 A
发送数据,必须等到 A 发送结束之后,B 才能给 A 发送数据。比如说对讲机。
全双工:
通信的时候,数据可以双向传输,并且可以同时传输。比如说我们打电话或者用通信软件进行语音和视频通话等。
半双工协议让 MySQL 通信简单快速,但是也在一定程度上限制了 MySQL 的性能,因为一旦从一端开始发送数据,另一端必须要接收完全部数据才能做出响应。
所以当批量插入的时候尽量拆分成多次插入而不要一次插入太大数据,同样的查询语句最好也带上 limit 限制条数,避免一次返回过多数据。
MySQL 单次传输数据包的大小可以通过变量 max_allowed_packet 控制,默认大小为 64MB(5.7 版本默认只有 4MB)。
执行以下语句查看 max_allowed_packet 变量大小:

2.2. 查询缓存
缓存命中检查:
如果开启了查询缓存(Query Cache),MySQL 会直接检查是否有完全相同的查询结果缓存。
命中:直接返回缓存结果。
未命中:进入后续流程,并可能将结果写入缓存(取决于配置)。
注意:MySQL 8.0 已移除查询缓存功能。
移除原因:
因为 MySQL 的缓存使用条件非常苛刻,是通过一个大小写敏感的哈希值去匹配的,这样就是说一条查询语句哪怕只是有一个空格不一致,都会导致无法使用缓存。而且一旦表里面有一行数据变动了,那么关于这种表的所有缓存都会失效,所以一般我们都是不建议使用缓存。
在 MySQL 8.0 版本之前缓存也是默认关闭的,可以通过变量 query_cache_type 进行控制。
2.3. 语法解析(Parser)
词法分析:将 SQL 语句拆分为 token(如关键字、标识符、操作符等)。
语法分析:根据 SQL 语法树规则,检查语句合法性(如SELECT * FROM table是否符合语法)。
生成抽象语法树(AST):将 SQL 转换为数据库可理解的内部结构。
整个sql语句会被分割成:select,name,from,table,where,id,=,1这几个字符。并且能识别出关键字和非关键字,然后根据 sql 语句生成一个数据结构,也叫做解析树。
如下图所示:

2.4、执行sql
如下图所示:

1. 预处理(Preprocessor)
语义检查:
生成逻辑查询计划:
2. 查询优化器(Optimizer)
其目标是生成最优的执行计划(即最小资源消耗、最快响应时间)。
优化步骤:
选择访问路径:决定是否使用索引(如全表扫描 vs 索引扫描)。如果有多个索引,选择最合适的索引。
连接顺序优化(针对多表查询):决定表的连接顺序(如 A JOIN B JOIN C 的顺序)。使用动态规划或代价模型(Cost Model)计算最优顺序。
其他优化:优化子查询(如转换为 JOIN)。优化排序(ORDER BY)和分组(GROUP BY)。常量传播、条件简化等。
输出执行计划:生成物理执行计划(如使用哪个索引、连接算法等)。
3. 执行器(Executor)
执行查询计划:
权限二次检查:
数据处理:
2.5. 存储引擎交互
存储引擎接口:
InnoDB 的处理:
其他引擎:
2.6. 返回结果
结果集组装:
分页处理:
返回客户端:
MySQL 将查询结果返回是一个增量的逐步返回过程。
当处理完所有查询逻辑并开始执行查询并且生成第一条结果数据的时候,MySQL 就可以开始逐步的向客户端传输数据了。这么做的好处是服务端无需存储太多结果,从而减少内存消耗。
3、示例流程(SELECT 查询)
以SELECT * FROM users WHERE id = 1;为例:
4、常见问题与优化
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持Linux运维。




















