mysql:一条SQL查询语句是如何执行的?


本篇文章会分析下一个 sql 语句在 MySQL 中的执行流程 。包括 sql 的查询在 MySQL 内部会怎么流转 。sql 语句的更新是怎么完成的 。
在分析之前我会先带着你看看 MySQL 的基础架构 。知道了 MySQL 由那些组件组成已经这些组件的作用是什么 。可以帮助我们理解和解决这些问题 。
一 MySQL 基础架构分析
1.1 MySQL 基本架构概览
下图是 MySQL 的一个简要架构图 。从下图你可以很清晰的看到用户的 SQL 语句在 MySQL 内部是如何执行的 。
先简单介绍一下下图涉及的一些组件的基本作用帮助大家理解这幅图 。在 1.2 节中会详细介绍到这些组件的作用 。
连接器: 身份认证和权限相关(登录 MySQL 的时候) 。
查询缓存: 执行查询语句的时候 。会先查询缓存(MySQL 8.0 版本后移除 。因为这个功能不太实用) 。
分析器: 没有命中缓存的话 。SQL 语句就会经过分析器 。分析器说白了就是要先看你的 SQL 语句要干嘛 。再检查你的 SQL 语句语法是否正确 。
优化器: 按照 MySQL 认为最优的方案去执行 。
执行器: 执行语句 。然后从存储引擎返回数据 。

mysql:一条SQL查询语句是如何执行的?

文章插图
简单来说 MySQL 主要分为 Server 层和存储引擎层:
Server 层:主要包括连接器、查询缓存、分析器、优化器、执行器等 。所有跨存储引擎的功能都在这一层实现 。比如存储过程、触发器、视图 。函数等 。还有一个通用的日志模块 binglog 日志模块 。
存储引擎: 主要负责数据的存储和读取 。采用可以替换的插件式架构 。支持 InnoDB、MyISAM、Memory 等多个存储引擎 。其中 InnoDB 引擎有自有的日志模块 redolog 模块 。现在最常用的存储引擎是 InnoDB 。它从 MySQL 5.5.5 版本开始就被当做默认存储引擎了 。
1.2 Server 层基本组件介绍
1) 连接器
连接器主要和身份认证和权限相关的功能相关 。就好比一个级别很高的门卫一样 。
主要负责用户登录数据库 。进行用户的身份认证 。包括校验账户密码 。权限等操作 。如果用户账户密码已通过 。连接器会到权限表中查询该用户的所有权限 。之后在这个连接里的权限逻辑判断都是会依赖此时读取到的权限数据 。也就是说 。后续只要这个连接不断开 。即时管理员修改了该用户的权限 。该用户也是不受影响的 。
2) 查询缓存(MySQL 8.0 版本后移除)
查询缓存主要用来缓存我们所执行的 SELECT 语句以及该语句的结果集 。
连接建立后 。执行查询语句的时候 。会先查询缓存 。MySQL 会先校验这个 sql 是否执行过 。以 Key-Value 的形式缓存在内存中 。Key 是查询预计 。Value 是结果集 。如果缓存 key 被命中 。就会直接返回给客户端 。如果没有命中 。就会执行后续的操作 。完成后也会把结果缓存起来 。方便下一次调用 。当然在真正执行缓存查询的时候还是会校验用户的权限 。是否有该表的查询条件 。
MySQL 查询不建议使用缓存 。因为查询缓存失效在实际业务场景中可能会非常频繁 。假如你对一个表更新的话 。这个表上的所有的查询缓存都会被清空 。对于不经常更新的数据来说 。使用缓存还是可以的 。
所以 。一般在大多数情况下我们都是不推荐去使用查询缓存的 。
MySQL 8.0 版本后删除了缓存的功能 。官方也是认为该功能在实际的应用场景比较少 。所以干脆直接删掉了 。
3) 分析器
MySQL 没有命中缓存 。那么就会进入分析器 。分析器主要是用来分析 SQL 语句是来干嘛的 。分析器也会分为几步:
第一步 。词法分析 。一条 SQL 语句有多个字符串组成 。首先要提取关键字 。比如 select 。提出查询的表 。提出字段名 。提出查询条件等等 。做完这些操作后 。就会进入第二步 。
第二步 。语法分析 。主要就是判断你输入的 sql 是否正确 。是否符合 MySQL 的语法 。
完成这 2 步之后 。MySQL 就准备开始执行了 。但是如何执行 。怎么执行是最好的结果呢?这个时候就需要优化器上场了 。
4) 优化器
优化器的作用就是它认为的最优的执行方案去执行(有时候可能也不是最优 。这篇文章涉及对这部分知识的深入讲解) 。比如多个索引的时候该如何选择索引 。多表查询的时候如何选择关联顺序等 。
可以说 。经过了优化器之后可以说这个语句具体该如何执行就已经定下来 。
5) 执行器
当选择了执行方案后 。MySQL 就准备开始执行了 。首先执行前会校验该用户有没有权限 。如果没有权限 。就会返回错误信息 。如果有权限 。就会去调用引擎的接口 。返回接口执行的结果 。

推荐阅读