一条mysql语句是如何执行的

97 阅读5分钟

运行着的MySQL服务器程序和客户端程序本质上都是计算机上的进程。因此,服务器向客户端发送请求并得到回复的过程本质上是一个进程间通信的过程。无论MySQL的客户端进程和服务器进程是通过TCP/IP、命名管道和共享内存,还是Unix域套接字文件来进行通信,最后实现的效果都是:客户端进程向服务器进程发送一段文本(MySQL语句),服务器进程处理后再向客户端进程发送一段文本(处理结果)。那么服务器进程对请求做了什么处理呢?

客户端进程可以向服务器进程发送增删改查的请求,下面以查询请求为例展示过程。

1. 连接管理

客户端进程可以通过TCP/IP、命名管道和共享内存,还是Unix域套接字文件来与服务端进程进行连接。每当一个客户端进程连接到服务器进程,服务器进程都会创建一个线程来处理与客户端的交互。但是,一旦线程分配过多也会严重影响系统性能,所以会采取办法来限制同时连接到服务器进程的客户端数量。

在客户端程序发起连接的时候,需要发送主机信息、用户名、密码,服务器程序会对客户端程序提供的信息进行认证,如果认证失败了,服务器程序会拒绝连接。倘若客户端程序和服务端程序不在同一台计算机中,我们还可以采用SSL(安全套接字)的网络连接来进行通信,来保证数据的传输安全。

当客户端和服务器断开连接时,服务器不会把该客户端对应的线程销毁,而是把它缓存起来,在与另一个新的客户端建立连接时,把这个缓存的线程分配给它。这样可以减少因频繁创建和销魂线程带来的开销。

客户端程序和服务器程序建立连接后,客户端程序对应的线程会等待客户端程序发送请求,该文本消息还需要继续处理~

解析与优化

2. 解析与优化

2.1. 查询缓存

MySQL服务器程序会把刚刚处理过的查询请求和结果缓存起来,如果下次有一摸一样的请求过来,直接从缓存中查找结果就好了。这个查询缓存可以在不同的客户端程序之间共享,换句话说,客户端A刚刚查询了一个语句,而客户端B之后发送了同样的查询请求,那么客户端B的这次查询就可以直接使用查询缓存中的数据。

但是,MySQL服务器对于查询缓存的要求十分严格。如果两个查询请求在任何字符上不同(例如,空格、注释、大小写),都会导致缓存不会命中。另外,如果查询请求中包含某些系统函数、用户自定义变量和函数、一些系统表,如mysql、information_schema数据库中的表,那这个请求就不会被缓存。

缓存一定会有失效的时候。MySQL的缓存系统会监测涉及到的每张表,只要该表的结构或者数据被修改了,那么该表的所有高速缓存查询都将无效并且被删除。

注意:从MySQL 5.7.20开始,不推荐使用查询缓存,并在MySQL 8.0中删除

2.2. 语法解析

如果查询缓存没有命中,就要进入正式的查询阶段。由于客户端发送过来的是一段文本,MySQL需要对这段文本做分析,判断请求的语法是否正确,然后从文本中将要查询的表、各种查询条件都提取到MySQL服务器内部使用的一些数据结构中。其中,从文本中提取我们需要的信息本质上算是一个编译过程,涉及词法解析、语法分析、语义分析等阶段。本文不展开描述。

2.3. 查询优化

语法解析之后,服务器程序获取到了需要的信息,比如要查询的是哪个列、哪个表等。但是MySQL语句执行的效率并不是很高。MySQL的优化程序会对我们的语句做一些优化,如外连接转化为内连接、表达式简化等。

3. 存储引擎

到目前为止,还没有真正的去访问数据表。MySQL服务器把数据的存储和提取操作都封装到了存储引擎中。

表由一行一行的记录组成,但这只是一个逻辑上的概念,物理上如何表示记录,怎么从表中读取数据,怎么把数据写入具体的物理存储器中,这都是存储引擎负责的功能。

为了管理上的方便,人们把连接管理、查询缓存、语法解析、查询优化这些不涉及真实数据存储的功能划分为MySQL Server的功能,把存取数据的功能划分为存储引擎的功能。各种不同的存储引擎向上边的MySQL Server层提供统一调用的api接口,包含了几十个底层函数,像“插入记录”、“读取索引第一条内容”等。

因此,当MySQL Server完成查询优化后,只需按照生产的执行计划调用调用底层存储引擎提供的api,获取到数据后返回给客户端就行

以上内容来自《MySQL是怎样运行的:从根儿上理解MySQL》的学习总结,salute。