MySQL篇--深入理解MySQL的结构(看这一篇就足够了)

我们使用关系型数据库的时间很长,但是有多少人是真正去理解MySQL的结构的?想不想知道,我们在进行一条MySQL查询语句的时候经历了什么?我们一一解答。

一、MySQL的逻辑结构图

可能有的童鞋对逻辑结构图中的逻辑两字又懵圈了,什么是逻辑图?

所谓逻辑图,就是按照处理流程画出的示意图(就是有些人的口头禅,按照逻辑应该是怎样怎么样)它区别于物理结构,不涉及具体的硬件信息。
MySQL篇--深入理解MySQL的结构(看这一篇就足够了)
 二、MySQL逻辑图详解

为什么要对逻辑图进行详解?

我不知道大家有没有接触过需求分析,需求分析的目的就是将业务之间的相关性,约束逻辑分析清楚(就是我们说的业务限制)。同样,对逻辑图的解释,会让大家在脑海中形成一个完整的处理逻辑,清楚结构中每个地方是做什么的,后期做的所有优化,都是基于这个逻辑图,这就是知其然还要知其所以然。

MySQL的逻辑结构分为三部分:MySQL客户端与服务端之间的交互,MySQL服务端的核心处理区,存储引擎。下面我们对着三部分中涉及的细项逐一说明。

1、客户端与服务端之间的交互

对应图上的①部分。大家如果是做软件的,应该接触过前后端交互的情形,如果没接触过,说明刚入职。

我们使用前后端分离框架定义接口文档时候,需要明确告诉前端我们使用的协议(http还是其他)和请求方式,并且是需要接口认证的,比如说你们常用的access-token。任何客户端和服务端分离的架构,在客户端与服务端交互时候都需要对应的协议+连接处理+授权+安全认证!

大家不要觉得这东西有多深奥,除了第一个吃螃蟹的人外,其他人都是站在别人的肩膀上发明东西,所以很多时候,设计思想都是相通的,要不然也不会有设计模式这本书了!

回归正题,MySQL客户端与服务端之间的交互,是使用TCP/IP协议的,在我们使用navicat等客户端工具连接MySQl服务端的时候,需要填写数据库用户的用户名和密码,这就是要与服务端建立连接,服务端需要验证连接属性是否正确,如果验证通过,会授权用户进行访问。

那连接建立之后呢?

连接建立后,客户端和服务端就要进行数据交互了。我记得在大学那会,学习网络通信时候,说网络通信的方式有单双工模式和全双工模式。我们的MySQL中客户端与服务端的交互使用的是半双工模式。

估计很多人又懵圈了,什么是半双工模式?

这些专家就喜欢发明这些名词,让你们各种懵,不懵显得学问不深哪!所谓半双工,举个最简单的例子,就是小白和小明打架约定,小白打一拳,小明回一拳。两人都能出拳,但是不能同时出拳(小白和小明都很傻)。半-双-工模式,半就是在一方进行数据传输时,另外一方不能发送数据;双,就是双方都可以发送数据;工就是工作模式。合起来就是,半双工模式就是在客户端进行数据发送时候,服务端不能进行数据传输,服务端发送数据时,客户端不能发送数据的一种工作模式。

当然了,传输的数据不能是无限制的,要不然被攻击了怎么整?在MySQL中,需要在服务端安装时候,设置max_allowed_packet(最大允许的包字节数),超过这个数值,请求是被拒绝的。


MySQL篇--深入理解MySQL的结构(看这一篇就足够了)
 

2、MySQL服务端的核心处理区

包含了图上的②③④⑤⑥。我们逐一介绍。

(1)查询缓存:查询缓存对应图中的②过程。在解析一个查询语句前,需要先看缓存设置,如果查询缓存是打开的(select @@query_cache_type),那么MySQL会检查一个查询语句是否命中了缓存数据,如果命中,直接返回结果,如果没命中,则需要进行③解析步骤(当然,这个过程服务端会检查用户是否具备查询权限,这回就知道为啥需要对每个用户进行各种赋权操作了吧,你没有查询权限还查个什么东东)。


MySQL篇--深入理解MySQL的结构(看这一篇就足够了)

既然涉及到了缓存,那就不得不说说MySQL缓存的存储方式。缓存的存储方式都是类似的,无非就是key-value方式。

show VARIABLES like '%query_cache%';--查看缓存相关属性(是否可用等等)

show STATUS like '%Qcache_hits%';--查看缓存的命中次数

另外一个问题,是不是所有的SQL结果都会缓存?

不会。有些经常变化的查询结果是不会被缓存的。比如我们常用的时间函数,它随时间变化,缓存结果毫无意义。

 (2)语法解析和预处理:在③中,主要涉及SQL语句的语法解析和预处理过程。解析器通过语法解析过程,将SQL语句解析成解析树。在解析过程中,解析器会根据定义的语法规则,看是否存在语法错误(关键字是否正确,比如select我写成了selele,执行时候会报错:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'slelec NOW() from DUAL' at line 1)。预处理器则会进一步去检查解析树是否合法,比如表的列是否存在,语句中表的字段是否存在等等。

 (3)查询优化:在④中,进行的是查询优化。在③过程中,生成了对应的语句解析树,在预处理过程中,验证解析树合法。那么下一步我们的MySQL就要对语法树做查询优化了(这样做的目的就是为了尽可能的提高执行效率,要不然谁用呢)。执行一条语句,可能会产生多种执行计划,每一种计划都有对应的开销(包含网络IO的开销和CPU的开销)。查询优化器的作用就是基于成本开销,预测一个查询使用某个执行计划的成本,并选取开销最小的那个计划去执行。在MySQL可以通过查询当前会话的last_query_cost的值,来查看上一次执行的成本开销(注意:这里的开销不是指时间)。

MySQL篇--深入理解MySQL的结构(看这一篇就足够了)
在查询优化阶段,MySQL需要做的另外一件事情就是根据生成的解析树,为树中涉及到的每一张表都生成一个处理器(handler)实例,这一步在查询执行引擎的时候会用到。 

 (4)查询执行引擎:对应过程⑤。在经过前面一系列步骤后,终于找到了一个查询优化器认为开销最小的执行计划(为什么说是查询优化器认为?大家想想,我们下一篇答疑)。那么,下一步就是要执行计划了,这一步就用到了查询执行引擎。查询执行引擎是通过存储引擎提供的API接口完成查询操作的,查询过程使用查询优化步骤中生成的处理器实例,去获取表的各种信息(如索引,列项等)。当然,存储引擎提供的接口都是原子功能,整个查询过程需要各个接口组合调用。

 (5)返回结果给客户端:对应过程⑥。在这个过程中,查询执行引擎会将查询结果返回给客户端,这里面包含结果集,查询花费的时间,影响的行数。如果查询缓存是ON状态,那么这个过程会将可以缓存的查询结果进行缓存。

3、存储引擎

存储引擎是MySQL的发动机,没有它,上面做的任何步骤都没有意义。在平常的优化中,都会根据存储引擎存储数据的规则去做对应的优化。

在MySQL中,默认使用的存储引擎是InnoDB,并且是不可禁用的。

那我们如何知道运行时有哪些可用的存储引擎?有两种方式:

使用SHOW ENGINES

或者SELECT ENGINE,SUPPORT FROM INFORMATION_SCHEMA.ENGINE;

MySQL篇--深入理解MySQL的结构(看这一篇就足够了)
 

MySQL篇--深入理解MySQL的结构(看这一篇就足够了)
 

相关推荐