02_MySQL 的架构设计
约 1863 字大约 6 分钟
2024-08-10
线程:处理网络连接
先思考一个问题,数据库连接池中的某个连接接收到了网络请求,那么谁来负责监听这个连接的网络请求?谁来负责把请求数据从网络连接里读取出来?
如果有了解过计算机基础知识,可能会知道一点,那就是网络连接必须分配给一个线程去处理,由一个线程来监听请求以及读取请求的数据
比如从网络连接中读取和解析出来一条业务系统发送的 SQL 语句,如下图所示

SQL 接口:处理接收到的 SQL 语句
我们接着思考一下,当 MySQL 内部的工作线程从一个网络连接中读取出来一个 SQL 之后,会如何来执行这个 SQL 语句呢?
我们可以很轻松的学会使用 SQL 语句,但是执行这个 SQL 语句去完成底层数据的增删改查,这就非常复杂了
所以 MySQL 内部首先提供了一个组件,那就是 SQL 接口(SQL Interface),专门用来执行我们发送给 MySQL 的 SQL 语句
因此 MySQL 的工作线程接收到 SQL 语句之后,就会转交给 SQL 接口去执行,如下图

查询解析器:让 MySQL 能看懂 SQL 语句
我们再接着思考一下,SQL 接口怎么执行 SQL 语句呢?直接把 SQL 语句交给 MySQL,他能看懂和理解这些 SQL 语句吗?
假设我们现在有这么一个 SQL 语句
select id, name, age from user where id = 1;如果是懂 SQL 语法的人立马就能看懂,但是 MySQL 本身就是一个数据库管理系统,他没法直接理解这些 SQL 语句
所以此时有一个关键组件出场了,那就是查询解析器
查询解析器负责对 SQL 语句进行解析,比如将上面这个 SQL 语句拆解成以下几个部分:
1、从
user表查询数据2、查询
id字段值等于1的数据3、从查询出来的数据中提取
id, name, age这三个字段
所谓的 SQL 解析就是按照既定的 SQL 语法,对我们按照 SQL 语法规则编写的 SQL 语句进行解析,然后理解这个 SQL 语句要做什么事情,如下图所示

查询优化器:选择最优的查询路径
通过解析器理解了 SQL 语句要干什么之后,接着就会找查询优化器选择一个最优的查询路径
查询优化器的工作原理后续我们会重点分析,我们先用一个简单的例子来理解一下所谓的最优查询路径是什么
还是用前面那个 SQL,从 user 表查询 id 字段值等于 1 的数据,从查询出来的数据中提取 id, name, age 这三个字段,要做什么明白了,但是应该怎么来实现呢?
要完成这个查询我们有以下几个查询路径(单纯用来理解,不代表真实的 MySQL 原理)
1、直接定位到
user表中id字段值等于1的数据,从查询出来的数据中提取id, name, age这三个字段的值2、把
user表中每一行数据的id, name, age三个字段的值都查出来,然后从查询到的数据中过滤出来id字段值等于1的数据,取id, name, age三个字段的值
看完上面两种实现路径,我们可以发现,要完成这个 SQL 语句的目标,两个路径都可以做到,但是哪一种更好呢?
显然感觉第一种查询路径会更好一些,查询优化器大概就是干这个事情的,针对 SQL 语句生成查询路径树,然后从里面选择一条最优的查询路径
相当于会告诉你,应该按照什么样的步骤和顺序,去执行哪些操作,然后一步一步的把 SQL 语句完成,如下图所示

存储引擎:真正执行 SQL 语句
最后一步,将查询优化器选择的最优查询路径交给底层的存储引擎去真正的执行。存储引擎是 MySQL 架构设计中很有特色的一个环节
真正执行 SQL 语句的时候,要么是更新数据,要么是查询数据,那么数据你觉得存放在哪里呢?
数据库本身也是编程语言写出来的一个系统,启动之后也是一个进程,执行系统里面的各种代码。对数据库而言,我们的数据要么放在内存里,要么就放在磁盘文件里
假设我们的数据有的存放在内存里,有的存放在磁盘文件里,我们已经知道了一个 SQL 语句要如何执行,那我们现在怎么知道哪些数据在内存里?哪些数据在磁盘里?我们执行的时候是更新内存的数据,还是更新磁盘的数据?如果是更新磁盘的数据,那是先查询哪个磁盘文件,再更新哪个磁盘文件?
所以这个时候就需要存储引擎了,在执行 SQL 语句的时候,他会按照一定的步骤去查询内存缓存数据,更新磁盘数据,查询磁盘数据等等,如下图所示

MySQL 架构设计中,SQL 接口、SQL 解析器、查询优化器都是通用的,就是一套组件
但是存储引擎的话,MySQL 是支持各种各样的存储引擎的,比如常见的 InnoDB、MyISAM、Memory 等等,我们是可以选择使用哪种存储引擎的
现在 MySQL 一般都是使用 InnoDB 存储引擎
执行器:根据执行计划调用存储引擎的接口
看完存储引擎我们回过头来思考一个问题,存储引擎可以去访问内存以及磁盘上的数据,那么是谁来调用存储引擎接口的呢?
答案是执行器,执行器会根据优化器选择的执行方案,按照一定的顺序和步骤去调用存储引擎的接口,把 SQL 语句的逻辑给执行了
举个例子,比如执行器可能会调用存储引擎的一个接口,去获取 User 表的第一行数据,然后判断 id 字段的值是否等于我们期望的一个值,如果不是的话就继续调用存储引擎的接口,去获取 User 表的下一行数据
基于上述的思路,执行器会根据优化器生成的一套执行计划,然后不停的调用存储引擎的各种接口去完成 SQL 语句的执行计划,如下图所示
