
MySQL语句执行流程
MySQL 语句执行流程
客户端进程向服务器进程发送一段文本(MySQL语句),服务器进程处理后再向客户端进程发送一段文本(处理结果)。这里我们以比较复杂的查询请求为例,来看一下服务器进程对客户端进程发送的请求做了什么处理,才能产生最后的处理结果。
从图中可以看到服务器在处理客户端的查询请求时,大致分为 3 部分:连接管理、解析与优化、存储引擎。下面来具体看看都做了什么。
连接管理
每当有一个客户端进程连接到服务器进程时,服务器进程都会创建一个线程专门处理与这个客户端的交互;当该客户端退出时会与服务器断开连接,服务器并不会立即把与该 客户端交互的线程销毁,而是把它缓存起来,在另一个新的客户端再进行连接时,把这个缓存的线程分配给该新客户端。避免了线程的频繁创建和关闭造成的资源浪费。
客户端程序发起连续时,需要携带主机信息、用户名、密码等信息,服务器程序会对客户端程序提供的这些信息进行认证.如果认证失败,服务辑程序会拒绝连接。当连接建立后,与该客户端关联的服务器线程会一直等待客户端发送过来的请求。MySQL服务器接收到的请求只是一个文本消息,该文本消息还要经过各种处理。
解析与优化
经过创建连接,现在 MySQL 服务器已经获得了文本形式的请求,接着需要经过后续处理,其中几个比较重要的部分分别是查询缓存、语法解析和查询优化。
查询优化
MySQL 服务器程序处理查询请求的过程也是这样,会把刚刚处理过的查询请求和结果缓存起来。如果下一次有同样的请求过来,直接从缓存中查找结果就好了,就不用再去底层的表中查找了。这个查询缓存可以在不同的客户端之间共享,也就是说,如果客户端A刚刚发送了一个查询请求,而客户端B之后发送了同样的查询请求,那么客户端B的这次查询就可以直接使用查询缓存中的数据了。
但是,MySQL 服务器没有那么聪明,如果两个查询请求有任何字符上的不同,如空格、注释、大小写,都会无法命中缓存。另外,如果查询请求中包含某些系统函数、用户自定义变量和函数、系统表,如mysql、information_schema、performance_schema数据库中的表, 则这个请求就不会被缓存。还有一些函数例如 NOW,每次调用都会产生最新时间。
不过既然是缓存,那就有失效的时候。MySQL 的缓存会检测涉及到的每张表,只要表结构或者数据被修改,如使用 INSERT、UPDATE、DELETE、TRUNCATE TABLE、ALTER TABLE、DROP TABLE 或 DROP DATABASE 语句,则与该表有关的所有查询都将失效并从查询缓存中删除!
虽然查询缓存有时可以提升系统性能,但也不得不因维护这块缓存而造成一些开销。比如每次都要去查询缓存中检索,查询请求处理完后需要更新查询缓存,需要维护该查询缓存对应的内存区域等。因此从MySQL 5.7.20开始,不推荐使用查询缓存,在 MySQL8.0中更是直接将其删除。
语法解析
如果查询缓存没有命中,接下来就需要进入正式的查询阶段。因为客户端发过来的请求只是一段文本,所以 MySQL 服务器首先要对这段文本进行分析,判断语法是否正确,然后从文本中将要查询的表、各种查询条件都提取出来放到 MySQL 服务器内部使用的一些数据结构上。
从本质上来说,这个从指定的文本中提取出需妥的信息算是一个编译过程,涉及词法解析、语法分析、语义分析等阶段。
查询优化
在语法解析之后,服务器程序获得到了需要的信息,比如要查询的表和列是哪些、搜索条件是什么等。但光有这些是不够的,因为我们写的MySQL语句执行起来效率可能并不是很高,MySQL的优化程序会对我们的语句做一些优化,如外连接转换为内连接、表达式简化、 子查询转为连接等一堆东西。优化的结果就是生成一个执行计划,这个执行计划表明了应该使用哪些索引执行查询,以及表之间的连接顺序是啥样,等等。我们可以使用 EXPLAIN 语句来查看某个语句的执行计划。
存储引擎
到 MySQL 服务器完成了查询优化为止,还没有真正地去访问真实的表中数据。MySQL 服务器把数据的存储和提取操作都封装到了一个名为存储引擎的模块中。为了实现不同的功能, MySQL提供了各式各样的存储引擎,不同存储引擎管理的表可能有不同的存储结构,采用的存取算法也可能不同。
MySQL 服务器处理请求的过程简单地划分为 server 层和存储引擎层。
连接管理、查询缓存、语法解析、查询优化这些并不涉及真实数据存取的功能划分为server层的功能,存取真实数据的功能划分为存储引擎层的功能。各种不同的存储引擎为 server 层提供统一的调用接口,其中包含了几十个不同用途的底层函数。
所以在 server 层完成了查询优化后,只需按照生成的执行计划调用底层存储引擎提供的 接口获取到数据后返回给客户端就好了。不过需要注意的一点是 server 层和存储引擎层交互时,一般是以记录为单位的。以 SELECT 语句为例,server 层根据执行计划先向存储引擎层取一条记录,然后判断是否符合 WHERE 条件;如果符合,就发送给客户端,否则跳过该记录, 然后继续向存储引擎索要下一条记录;依此类推。
server层在判断某条记录符合要求之后,其实是先将其发送到一个缓冲区,待到该缓冲区满了,才向客户端发送真正的记录。该缓冲区大小由系统变量 net_buffer_length 控制。
常用存储引擎
MySQL 支持多种存储引擎,以下列出部分存储引擎:
存储引擎 | 描述 |
---|---|
ARCHIVE | 用于数据存档(记录插入后不能再修改) |
BLACKHOLE | 丢弃写操作,读操作会返回空内容 |
CSV | 在存储数据时,以逗号分隔各个数据项 |
FEDERATED | 用来访问远程表 |
InnoDB | 支持事务、行级锁、外键 |
MEMORY | 数据只存储在内存,不存储在磁盘:多用于临时表 |
MERGE | 用来管理多个MyISAM表构成的表集合 |
MyISAM | 主要的非事务处理存储引擎 |
NDB | MySQL集群专用存储引擎 |
们最常用的就是 InnoDB 和 MyISAM,偶尔还会提一下 MEMORY。其中 InnoDB 是MySQL默认的存储引擎。
功能 | MyISAM | MEMORY | InnoDB | ARCHIVE | NDB |
---|---|---|---|---|---|
B-tree indexes | √ | √ | √ | ||
Backup/point-in-time recovery | √ | √ | √ | √ | √ |
Cluster database support | √ | ||||
Cluster indexes | √ | ||||
Compressed data | √ | √ | √ | ||
Data caches | √ | √ | |||
Encrypted data | √ | √ | √ | √ | √ |
Foreign key support | √ | √ | |||
Full-text search indexes | √ | √ | |||
Geospatial data type support | √ | √ | √ | √ | |
Geospatial indexing support | √ | √ | |||
Hash indexes | √ | √ | |||
Index caches | √ | √ | √ | ||
Locking granularity | 表 | 表 | 行 | 行 | 行 |
MVCC | √ | ||||
Query cache support | √ | √ | √ | √ | √ |
Replication support | √ | 有限 | √ | √ | √ |
Storage limits | 256 TB | RAM | 64 TB | 无存储限制 | 384 EB |
T-tree indexes | √ | ||||
Transactions | √ | √ | |||
Update statistics for data dictionary | √ | √ | √ | √ | √ |
InnoDB 从 MySQL 5.5.5 版本开始作为 MySQL 的默认存储引擎,之前版本的默认存储引擎为MyISAM。
- 感谢您的赞赏。