当我们想查询一条SQL时,通常会这样

mysql> select * from user where id = 1;

然后就会返回结果,但是我们并不知道它实际上会发生什么。

下面将从一个大的方向拆解一下它的过程。

逻辑架构图

0d2070e8f84c4801adbfa03bda1f98d9.png

大体上说,它可以分为Server层存储引擎层

  • Server层:主要包括连接器、缓存(8.0后废弃)、分析器、优化器、执行器,包括了MySQL大多数核心服务。
  • 存储引擎:主要负责数据的存储和提取,现在MySQL默认的存储引擎是InnoDB。

Server层

连接器

大白话地说,它就是管理所有客户端对MySQL的连接,它主要负责建立连接、获取权限、维持和管理连接。

在cmd中,一般都是这样写的:

mysql -u${username} -p${password}
image20220119215252683.png

当密码不正确时,会提示Access denied for user的提示;当密码正确之后,连接器会去权限表中查询你拥有的权限,以后这个连接里面的权限判断逻辑,都依赖于此时获取的权限。

这意味着,当你的权限被修改时,只要不断开连接,也不会对此有任何影响。

可以使用show processlist中查询连接的客户端。

image20220119215854130.png

这种连接分为短连接和长连接。短连接是指每次执行完几次查询后就断开,下次查询再连接上。这种做法不太好,因为建立连接的过程是复杂的,因此推荐使用长连接。但是全部使用长连接后,会发现内存占用很高,有可能导致MySQL异常重启。

如何解决?定期断开;重新初始化资源。

查询缓存

它是以k-v对形式出现的,key是查询的语句,value是查询的结果。如果两次查询的语句一样,直接返回结果,效率很高,但是并不建议开启缓存

查询缓存的失效非常频繁,只要有某些更新,那么缓存全部都无效。对于一些不常常变动的表,缓存的效果是极棒的,比如一些基础配置表,但是对于一些更新压力较大的表,那缓存的效果聊胜于无。

另外,从MySQL8.0开始,没有缓存这一块了,在此之前的版本可以按需配置,到8.0后想用都没得用咯,也正说明了它的鸡肋!

分析器

这里让我想起编译原理的内容。

当SQL进来后,首先进行词法分析,即判断这条SQL中,哪个单词对应哪部分,分别代表什么。以这条SQL为例:select * from user,词法分析需要析出select这个关键词,知道它是查询语句;分析出user是表名。

然后就是语法分析,会根据语法规则进行判断这个SQL是否满足语法要求,比如 selct * from user,它会发现这个语句不对,“You have an error in your SQL syntax”。

另外,在分析阶段,它也会判断表是否存在、列是否存在等等,不仅仅是词法分析和语法分析噢。

优化器

经过了分析器,MySQL就知道自己要做什么,但是在做之前,还需要进行一些优化。

比如当表有多个索引,决定使用哪个索引 ?

当有多表关联查询时,先查哪个表,后查哪个表?

从逻辑上,结果是一样的,但是执行效率是不同的,因此需要优化器做这个工作。细处以后再说。

执行器

真正开始执行语句。

首先,它会检查你有没有权限,如果没有,就会返回没有权限的错误。

如果有,则会打开表,根据引擎定义,去找执行引擎的接口查找数据。

还是以开头一句mysql> select * from user where id = 10;为例:

  1. 调用InnoDB引擎接口取这个表的第一行,判断id是否为10,如果不是则跳过,如果是则把结果放在结果集中。
  2. 调用引擎接口取“下一行”,同1的判断。
  3. 遍历所有的满足条件的行,返回结果集给客户端