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

  • 客户端发送一条sql给服务器,涉及到建立连接判断权限等。
  • 服务器先检查缓存,如果命中了查询缓存,则立即返回命中结果,否则进入下一阶段。
  • 服务器经过解析器,进行sql解析,生成解析树,然后通过预处理器处理解析树,再由查询优化器生成对应的执行计划。
  • 然后在调用存储引擎AOI来执行查询。
  • 将结果存入查询缓存,并返回给客户端。

2.建立连接

mysql客户端和服务器之间的通讯协议是“半双工”的,这意味着,在任何一个时刻,要么由服务器向客户端发送数据,要么由客户端向服务器发送数据,这两个动作不能同时发生。
客户端用一个单独的数据包将查询传给服务器,然后等待结果。
服务端响应可以是多个数据包,客户端必须完整的接受整个返回结果,然后断开连接。
如果客户端不断开连接,且没有任何操作,服务器超过了wait_timeout 参数的值就主动断开连接。

show variables like '%wait_timeout%';

mysql的执行过程 mysql的sql执行过程_服务器


这是线上配置的。

查看服务器最大连接数

show variables like 'max_connections';

查看正在执行的mysql连接

show processlist;

mysql的执行过程 mysql的sql执行过程_客户端_02

  • id列,线程的唯一标识,一个标识,你要kill一个语句的时候很有用。
  • user列,显示单前用户,如果不是root,这个命令就只显示你权限范围内的sql语句。
  • host列,显示这个语句是从哪个ip的哪个端口上发出的。呵呵,可以用来追踪出问题语句的用户。
  • db列,显示这个进程目前连接的是哪个数据库。
  • command列,显示当前连接的执行的命令,一般就是休眠(sleep),查询(query),连接(connect)。
  • time列,此这个状态持续的时间,单位是秒。
  • state列: 线程的状态。
  • info列,显示具体执行的sql语句。默认只显示前100个字符,要看全部信息,需要使用 show full processlist。

3.查询缓存

查询是否命中规则
Mysql 首先会将要缓存的结果放在引用表中,然后使用查询语句,数据库名称,客户端协议的版本等因素算出一个hash值,这个hash值与引用表中的结果相关联。如果在执行查询时,根据一些相关的条件算出的hash值能与引用表中的数据相关联,则表示查询命中。

查询缓存的不足

  • 查询缓存有个规则,如果数据表被更改,那么和这个数据表相关的全部Cache全部都会无效,并删除。降低了修改操作效率。
  • 查询缓存是由一个全局锁在控制,每次更新查询缓存的内存块都需要进行锁定。如果查询缓存配置的内存比较大且里面存放了大量的查询结果,当查询缓存失效的时候,会长时间的持有这个全局锁。因为查询缓存的命中检测操作以及缓存失效检测也都依赖这个全局锁,所以可能会导致系统僵死的情况。
  • 如果没有命中缓存,每次还先查查询缓存,导致效率低下。

查询缓存的管理

show variables like '%query_cache%';

mysql的执行过程 mysql的sql执行过程_客户端_03

  • query_cache_type : 0(0FF):关 1(ON)开 2(DEMAND)根据需要使用。
  • query_cache_size: 缓存的大小。
  • query_cache_limit : 查询缓存的最大值,结果集大于这个值将不会被缓存。

以上是我们线上的配置,对,线上最好不要开启查询缓存!! 要做缓存也是交给专门的redis等去做。

4.解析和预处理

解析器通过关键字将SQL语句进行解析,并生成对应的解析树。这一步就会验证是否使用错误的关键字,或者使用关键字的顺序是否正确等,再或者它还会验证引号是否能前后正确匹配。

预处理则根据一些MySQL规则进一步检查解析树是否合法,例如,这里将检查数据表和数据列是否存在,还会解析名字和别名,看看它们是否有歧义。

5.查询优化器

查询优化器会将解析树转化成执行计划。一条查询可以有多种执行方法,最后都是返回相同结果。优化器的作用就是找到这其中最好的执行计划。
生成执行计划的过程会消耗较多的时间,特别是存在许多可选的执行计划时。

优化器优化实例
(1) 假如有 WHERE col1 = col2 AND col2 = ‘x’; 依据传递性:如果A=B and B=C,那么就能得出A=C。所以上面的表达式mysql查询优化器能进行如下的优化:WHERE col1 = ‘x’ AND col2 = ‘x’;

(2) 查询优化器会对一些无用的条件进行过滤,比如说 WHERE 0=0 AND column1=‘y’  因为第一个条件是始终为true的,所以可以移除该条件,变为:WHERE column1=‘y’。

(3) 如下表达式:WHERE col1 = 1 + 2转化为:WHERE col1 = 3 Mysql会对常量表达进行计算,然后将结果生成条件。

(4) where a=1 and b=2 ,如果b有索引,a没有索引, 会把b=2先判断。