mysql45讲笔记-day01

一、mysql的执行过程

执行一条mysql的查询语句的主要流程如下

  1. 客户端向mysql服务端首先发起请求,通过mysql服务端的连接器获取到连接
  2. mysql的连接器需要处理一些,比如校验用户名密码是否正确,然后将校验的结果返回给客户端,建立连接,同时管理着连接
  3. 获取到连接以后,在服务端首先回去查询缓存,如果缓存中有数据,则将数据直接返回给用户,如果没有,则需要重新获取数据,走正常流程。
    • 这里需要补充的是:mysq服务端的缓存中,存储的key是这条sql语句,value存储的是这条sql语句执行的结果
  4. 正常的查询流程是,mysql服务端开始如果没有从缓存中获取到数据,又需要经过服务端的三个组件,分别是分析器,优化器和执行器,最后才能到存储引擎中获取数据。
  5. 分析器,主要功能是对查询语句进行词法分析和语法分析
  6. 解析器,主要功能是对查询语句进行优化,我们添加的索引也是在这一步中被使用,同时优化器还会生成执行计划,提供给执行器使用。
  7. 执行器,执行优化后的执行计划,并和存储引擎中获取数据,将数据返回。

mysql大体上可以分为两部分

  • server层
  • 存储引擎

在server层中又包含了连接器,分析器,优化器,和执行器的重要组成部分,此外,还包括一些常用的函数,比如日期转化,此外,所有跨存储引擎执行的操作,也都是在这一层实现的,比如,存储过程,触发器,视图等。

而存储引擎的主要功能就是数据的存储和提取。它的架构模式是插件式的,支持了InnoDB,MyISAM,Memory,等多种方式,从mydql5.5开始,默认的存储引擎为InnoDB。

连接器的主要作用:

  • 负责和客户端建立连接,获取权限,身份认证,维持和管理连接

每次连接以后,就有了对应的执行权限,如果你已经建立了一个连接,有人用root用户修改了你的权限,但是,只要你不断开连接,修改就不会生效,获取到的权限,还是你之前的权限列表,只有你断开连接,再次连接的时候,新的权限才会被保存。

客户单建立了连接如果长时间没有操作,就会断开连接,默认的时间是八小时,通过wait_timeout参数控制。

在数据库中,连接又分为两种类型

  • 长连接

    如果客户有持续的请求,则一直使用同一个连接

  • 短连接

    每次执行很少的请求,请求完成以后就断开连接了,下次使用的时候,重新建立连接。

    扫描二维码关注公众号,回复: 13588862 查看本文章

有时候使用长连接,可能会使得内存涨的很快,这是因为,mysql在执行过程中临时使用的内存是管理在连接对象中的。这些资源只有在连接断开的时候才会被释放。所以,如果一直保持长连接,可能会导致系统OOM,从现象上看就是mysql重启。

解决方案:

  • 定期断开长连接,使用一段时间后,或者在程序中判断执行过一个占用内存大的语句后,断开连接,如果下次还需要,则重新连接
  • 如果使用的是mysql5.7以后的版本,执行过一个占用内存很大的语句后,可以执行mysql_rest_connection来重新初始化连接对象。这个过程不需要重新连接和做权限校验,只是会将连接初始化成刚开始的状态。

关于mysql缓存

连接建立以后,会先去查询mysql的缓存,在mysql中缓存是直接保存在内存中的,通过key-value的形式存储,key是查询语句,value是查询的结果。如果查询缓存命中,则就将结果直接返回,否则继续后面的执行阶段。

但是mysql中不建议使用缓存,在mysql8中直接删除了缓存相关的阶段。

这是因为,在实际使用过程中,缓存命中的概率是很低的,我们 做了更新操作以后,缓存中的数据就是旧数据了,每次都会被删除 ,还没有使用,就被删除了。对于数据库来说,只是增加了压力,并没有得到实际的提升。除非数据是一些不会经常改变的数据可以使用缓存,否则不建议使用。

mysql 8中直接将缓存模块删除了。

分析器

查询如果没有命中索引,那就要开始执行sql语句了,首先,mysql需要知道你是要干什么,具体的来说,你是要执行curd中的那个操作。

我们输入的是一串字符串,包含字母和空格。mysql通过关键字select知道这是一条查询语句,会分别将表名和列名识别出来。这个过程就是词法分析的过程

做完识别以后,mysql 就要做语法分析了,语法分析器根据语法的规则,判断输入的sql是否满足mysql的语法。如果语句有异常,就会返回给客户端

优化器

优化器的主要作用是对语句的优化。

比如查询的表中有多个索引的时候,决定使用哪个索引。或者多表关联的时候,决定连接的顺序。

比如

select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;

这条语句,

  • 可以先查询t1表找到c=10的结果再和t2进行关联
  • 也可以先查询d=20的结果,再和t1关联

两种方案的逻辑执行结果都是一样,但是执行的效率是不同的。mysql的优化器就是为我们找到最优的那个。

执行器阶段完成后,整个语句的执行计划就确定下来了。

执行器

mysql通过分析器知道了我们需要做什么,通过优化器知道了怎么做,到了执行器整个阶段就是去具体的执行做的过程。

开始执行执行计划的时候,需要先判断一下对整个表有没有执行查询的权限。如果没有,返回异常。

如果有权限,就打开表,继续执行,打开表的时候,优化器就会根据表的引擎定义,去使用这个引擎提供的接口。

如果表中没有索引的执行流程大致如下:

  1. 调用InnoDB的引擎接口获取这个表的第一行,判断id值是不是10,如果不是,则跳过,如果是,则将数据保存在结果集中。
  2. 调用引擎接口获取下一行。重复判断相同的逻辑,直到这个表的最后一行。
  3. 执行器将上述遍历过程中所有符合的结果组成记录集作为查询结果,返回给客户端。

对于有索引的表,执行过程也差不多。只不过,第一次调用的时候满足条件的第一行,这个接口。之后循环调用满足条件的下一行。

每次调用一行的数据,mysql中有个字段rows_examined字段都会累加。

但是在有些情境下,执行器调用一次,在引擎内部则扫描了多行。所以,引擎扫描行和row_examined记录的值并不是完全相等。

猜你喜欢

转载自blog.csdn.net/hs_shengxiaguangnian/article/details/118708533