MySQL-逻辑架构
MySQL是一个典型的
C/S
架构,也就是Client/Server
结构,服务端就是mysqld
。不论客户端进程和服务器进程是采用的哪种方式通信,最后实现的效果都是:客户端进程向服务器进程发送一段文本(SQL语句),服务器进程处理后再向客户端进程发送一段文本(处理结果)。
这里以一个查询请求作为实例,MySQL服务端处理请求的流程图如下:
上面我们列举了一个MySQL查询的流程图,那么MySQL的具体的逻辑架构图如下:
连接器(Connectors)
Connectors
指的就是不同编程语言中和SQL的交互。MySQL首先是一个网络应用程序,在TCP之上定义了自己的应用层协议。所以要使用MySQL,我们可以编写代码和MySQL建立TCP连接,之后按照其定义好的协议进行交互。或者比较方便的办法就是调用SDK,比如Native API
、JDBC
、PHP
等各个语言的MySQL Connector,或者通过ODBC
。但是通过SDK来访问MySQL,本质上还是在TCP连接上通过MySQL的协议来和其交互。
MySQL服务端结构
从上面的图中我们可以看到MySQL服务端的结构大致可以分为连接层、服务层以及引擎层这三层。
连接层
客户端访问MySQL服务器之前,首先第一件事就是建立TCP连接,当经过三次握手连接建立成功后,MySQL服务器对TCP传输过来的账号密码做身份认证、权限获取。
- 用户名或密码不对:客户端会收到一个
Access denied for user
错误,客户端程序结束执行。 - 用户名和密码正确:会从权限表查出账号拥有的权限和连接关联,之后的权限判断逻辑,都将依赖于此时读到的权限。
那么一个系统只能和MySQL服务建立一个连接吗?只能有一个系统和MySQL服务建立连接吗?
答案是否定的,多个系统都可以和MySQL建立连接,每个系统建立的连接当然也不只是一个。所以为了解决TCP连接的无限创建和TCP频繁创建销毁带来的资源开销以及性能下降等问题,MySQL服务使用了TCP连接池来限制连接数量,采用长连接模式复用TCP连接。
TCP连接收到请求后,必须要分配一个线程专门和客户端交互。所以还会有一个线程池,来完成后面的流程。每个连接从线程池中获取线程,节省了创建和销毁线程的开销。
以上的内容都可以归纳到MySQl的连接层中。所以连接层的职责就是负责认证、管理连接、获取权限信息。
服务层
服务层主要是来完成大多数的核心功能的,比如SQL接口、查询缓存、SQL的分析和优化以及部分内置函数的执行。所有跨存储引擎的功能也在服务层实现,比如过程以及函数等。
在服务层中,MySQL服务会解析查询并且创建相应的内部解析树,对其完成相应的优化:比如确定查询表的顺序,是否利用索引等,最后生成相应的执行操作。
如果是SELECT
语句,服务器还会查询内部的缓存。如果缓存空间足够大,这样在解决大量读操作的环境中能很好的提升性能。
SQL Interface(SQL接口)
- 接收用户的SQL命令,并且返回用户需要查询的结构。比如
SELECT...FROM...
就是调用的SQL Interface
。 - MySQL支持DML(数据操作语言)、DDL(数据定义语言)、存储过程、视图、触发器、自定义函数等多种SQL语言接口。
Parser(解析器)
- 在解析器中对SQL语句进行语法分析、语义分析。将SQL语句分解成数据结构,并将这个结构传递到后续步骤,以后SQL语句的传递和处理就是基于这个结构的。如果在分解构成中遇到错误,那么就说明这个SQL语句是不合理的。
- 在SQL命令传递到解析器的时候会被解析器验证和解析,并为其创建语法树,并根据数据字典丰富查询语法树,会验证该客户端是否具有执行该查询的权限。创建好语法后,MySQL还会对SQL查询进行语法上的优化,进行查询重写。
Optimizer(查询优化器)
-
SQL语句在语法解析之后、查询之前会使用
Optimizer
(查询优化器)来确定SQL语句的执行路径,生成一个执行计划。 -
这个执行计划表明应该使用哪些索引来查询(全表检索或索引检索)、表之间的连接顺序如何。最后会按照执行计划中的步骤调用存储引擎提供的方法来真正的执行查询,并且将结果返回给用户。
-
使用
选取-投影-连接
策略进行查询。比如:SELECT id,name FROM t_user WHERE age = 18;
选取
:先根据WHERE
进行选取
,而不是将表全部查询出来以后再过滤。投影
:先根据id
和name
进行属性投影
,而不是将属性全部查询出来之后再过滤掉。连接
:将上面两个条件连接
起来生成最终的查询结果。
Caches & Buffers(缓存组件)
- MySQL内部维护着一些
Cache
和Buffer
,比如Query Cache
用来缓存一条SELECT
语句的执行结果。如果能够在其中找到对应的查询结果,那么就不必再进行查询解析、优化以及执行的整个过程了,会直接将结果返回给客户端。 - 这个缓存机制是由一系列小缓存组成的:比如表缓存、记录缓存、key缓存、权限缓存等等。
- 缓存是可以在不同的客户端之间共享的。
🚨从
MySQL5.7.20
开始,不再推荐使用查询缓存,并且在MySQL8.0
中删除了这个机制。
引擎层
和其他的数据库相比,MySQL有一点与众不同,它的架构可以在多种不同的场景中应用并且发挥良好的作用,主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其他的系统任务以及数据的存储相分离。这种架构可以根据业务的需求以及实际需要选择适合的存储引擎。同时开源的MySQL还允许开发人员开发自己的存储引擎。
插件式的存储引擎层,真正地负责了MySQL中数据地存储和提取,对物理服务器级别维护的底层数据执行操作。服务器通过API与存储引擎进行通信,而不同的存储引擎具有的功能不同,这样我们可以根据自己的实际需要进行选取。
在MySQL8.0.31
中默认支持的存储引擎如下:
mysql> SHOW ENGINES;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| ndbcluster | NO | Clustered, fault-tolerant tables | NULL | NULL | NULL |
| FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO |
| MyISAM | YES | MyISAM storage engine | NO | NO | NO |
| ndbinfo | NO | MySQL Cluster system information storage engine | NULL | NULL | NULL |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| CSV | YES | CSV storage engine | NO | NO | NO |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
11 rows in set (0.00 sec)
存储层
所有的数据、数据库/表的定义、表的每一行内容、索引都是存在文件系统上的,以文件的方式存在的,并完成与存储引擎的交互。当然有些存储引擎比如InnoDB,也支持不使用文件系统直接管理裸设备,但现代文件系统的实现使这样做没有必要了。在文件系统之下,可以使用本地磁盘,也可以使用DAS
、NAS
、SAN
等各种存储系统。
总结
开篇提到的架构图可以简化为下面这样: