MySQL 笔记(一)基础架构
一、整体概况
我们先通过一条简单的 SQL 聊一聊 MySQL 的基础架构。比如我们有个学生表,有 id,name,age 三个字段,执行如下语句时,它的内部执行过程是怎么样的呢?
从执行结果上看,我们执行了一条 SQL,给我们返回了 name='张三' 对应的这条记录。从 MySQL 的内部来看,它经过了 连接器、查询缓存、分析器、优化器、执行器等,最后到达存储引擎取出我们需要的数据。这些组件之间是如何协同工作的呢?让我们看下 MySQL 的逻辑架构图
由图上可以看出,MySQL 大体上可以分为 Server 层和存储引擎层两部分。
Server 层:包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
存储引擎层:负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始成为了默认存储引擎。
二、连接器
要使用 MySQL 数据库,第一步就是要连接上数据库,连接器就是负责这个连接操作的组件。连接器负责跟客户端建立连接、获取权限、维持和管理连接。连接一般分这么几种情况:
命令行连接:mysql -h$ip -P$port -u$user -p
工具连接:Navicat、SQLyog 等
代码连接:各种数据库连接池,如 druid 等
执行连接操作时,连接器会在完成经典的 TCP 握手后,开始认证你的身份,这个时候用的就是你输入的用户名和密码。
如果用户名或密码不对,你就会收到一个"Access denied for user"的错误,然后客户端程序结束执行。
如果用户名密码认证通过,连接器会到权限表里面查出你拥有的权限。之后,这个连接里面的权限判断逻辑,都将依赖于此时读到的权限。
要注意的是,一个用户成功建立连接后,即使你用管理员账号对这个用户的权限做了修改,也不会影响已经存在连接的权限。修改完成后,只有再新建的连接才会使用新的权限设置。
三、查询缓存
回到我们开头的那条 SQL,连接建立后,执行 SELECT 查询语句,会先到查询缓存里查询,如果命中,直接返回;否则,继续后面的执行阶段。通常情况下,我们不建议使用查询缓存,查询缓存往往弊大于利。
因为在业务开发中,对一个表的更新是非常频繁的,这会导致查询缓存的失效也非常频繁。除非有一张很长时间才会更新一次的静态表。比如,系统配置表,那这张表上的查询才适合使用查询缓存。但是即使是这种静态表,也不太建议使用数据库的查询缓存,一般会使用 Redis 或 Mybatis 缓存。值得注意的是,MySQL 8.0 版本直接将查询缓存的整块功能删掉了,也就是说 8.0 开始彻底没有这个功能了。
四、分析器
或者叫解析器,主要进行 SQL 解析、预处理操作。实际上,从分析器开始,才是真正开始执行 SQL 语句,因为这时才需要对 SQL 语句进行解析。分析器分为两步“词法分析”和“语法分析”两步,我们以开头的那条 SQL 为例
词法分析:你输入的是由多个字符串和空格组成的一条 SQL 语句,MySQL 需要识别出里面的字符串分别是什么,代表什么。如:MySQL 从你输入的 SELECT 这个关键字识别出来,这是一个查询语句。它也要把字符串 student 识别成“表名 student”,把字符串“name”识别成“列 name”。接着会进行“语法分析”。
语法分析:根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法。如果不满足语法,会返回“You have an error in your SQL syntax”错误提示。
五、优化器
分析器之后,MySQL 就知道你要做什么了。但是在开始之前会再经过一个优化器的处理,比如表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序等。这一步会生成执行计划。
六、执行器
MySQL 通过分析器知道了你要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句。
执行之前,会先判断该用户有没有执行查询的权限(如果命中查询缓存,会在查询缓存返回结果的时候,做权限验证。查询也会在优化器之前调用 precheck 验证权限)。
没有权限:返回没有权限的错误,如:ERROR 1142 (42000): SELECT command denied to user 'xxx'@'localhost' for table 'student'
有权限:继续往下执行,根据表的引擎定义,去调用这个存储引擎提供的接口。默认的存储引擎为 InnoDB 引擎。
七、小结
一条查询 SQL 的执行路径通常有这么几步:
客户端发送一条查询 SQL 给服务器
服务器先检查查询缓存(如果开启),如果命中了缓存,返回缓存的结果(返回之前会做权限验证);否则,进入下一阶段
服务器使用解析器对 SQL 进行解析、预处理。这一步会验证语法正确性并生成合法的解析树,也会做一些权限的验证
优化器根据解析器提供的解析树生成对应的执行计划
MySQL 根据优化器生成的执行计划,调用存储引擎的 API 来执行查询
将结果返回给客户端
这里,我参照《高性能 MySQL》画了下查询语句的执行路径图:
评论