MySQL 查询执行的基础(一)

273 阅读3分钟

本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!

前言

当向MySQL发送一个请求时,MySQL到底做了什么?

  1. 客户端发送一条查询给服务器。
  2. 服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果。否则进入下一阶段。
  3. 服务器端进行SQL解析、预处理,再由优化器生成对应的执行计划。
  4. MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询。
  5. 将结果返回给客户端。

MySQL客户端/服务器通信协议

MySQL客户端和服务器之间的通信协议是“半双工”的,这意味着,在任何一个时刻,要么是由服务器向客户端发送数据,要么是由客户端向服务器发送数据,这两个动作不能同时发生。一个时间只有一边可以发消息,一旦一端开始发送消息,另一端要接收完整个消息才能响应它。也就意味着没法进行流量控制。

服务器开始响应客户端请求时,客户端必须完整的接收整个返回结果才可以,只接受一部分是不可以的,所以必要时一定要加上limit限制。

查询状态

使用show full processlist命令就可以查询MySQL现在的状态,如果有Locked状态存在,就说明有死锁的情况出现,此时需要杀掉对应的线程 kill 线程Id

Command中的重要值:

sleep

线程正在等待客户端发送新的请求。

Query

线程正在执行查询或者正在将结果发送给客户端。

Locked

在MySQL服务器层,该线程正在等待表锁。在存储引擎级别实现的锁,例如InnoDB的行锁,并不会体现在线程状态中。对于MyISAM来说这是一个比较典型的状态,但在其他没有行锁的引擎中也经常会出现。

Analyzing and statistics

线程正在收集存储引擎的统计信息,并生成查询的执行计划。

Copying to tmp table [on disk]

线程正在执行查询,并且将其结果集都复制到一个临时表中,这种状态一般要么是在做GROUP BY操作,要么是文件排序操作,或者是UNION操作。如果这个状态后面还有“on disk”标记,那表示MySQL正在将一个内存临时表放到磁盘上。

Sorting result

线程正在对结果集进行排序。

还有很多其他的值,可以在

dev.mysql.com/doc/refman/…

这个页面找到

查询缓存

在解析一个查询语句之前,如果查询缓存是打开的,那么MySQL会优先检查这个查询是否命中查询缓存中的数据。这个检查是通过一个对大小写敏感的哈希查找实现的。查询和缓存中的查询即使只有一个字节不同,那也不会匹配缓存结果,这种情况下查询就会进入下一阶段的处理。

如果当前的查询恰好命中了查询缓存,那么在返回查询结果之前MySQL会检查一次用户权限。这仍然是无须解析查询SQL语句的,因为在查询缓存中已经存放了当前查询需要访问的表信息。如果权限没有问题,MySQL会跳过所有其他阶段,直接从缓存中拿到结果并返回给客户端。这种情况下﹐查询不会被解析,不用生成执行计划,不会被执行。