浅谈Mysql的查询过程与执行流程

场景:
响午时分,阳光透过窗户照在办公室的角落;刚写完CURD的我起身拿着水杯接水,路过雷神Z的身旁,看着他的望着刚执行完的两条SQL的语句,满意的露出笑容对我说道:“瞧,我的语句多么强大,轻松完成工作”,我回应到:“傻瓜,你的两条SQL语句,MySQL为你默默付出了多少!你知道嘛!”
身为后端的我们,每天与之打交道的就是数据库,我们不生产数据,我们只是数据的搬运工(这句话用在这个地方真是秒啊);所以知晓MySQL的执行流程就显得尤为重要,废话不多说,先拿出一张图唬住我雷神哥
浅谈Mysql的查询过程与执行流程
客户端与MySQL建立连接
当客户端发现有数据查询的操作时,就会去主动与MySQL去建立链接;接下来门卫大哥–连接器出场,进行你的身份验证:用户名、密码、端口,获取权限等,只要有某项不符合,那你就无法与之建立链接,被阻挡在大铁门外。
查询缓存
缓存这个词汇大家肯定都熟悉,就是把之前查询的一模一样的语句放入到缓存中去,以Key,Value的形式存放起来;每次查询的时候先去比对下缓存中是否存在,存在直接返回,不存在的话才会真正的走查询流程。
优点:可直接查询到结果集,不走查询流程大大提高了效率;
缺点:为保证数据的一致性,每次表中有数据更改,缓存都会被删除,对于更新比较频繁的数据表,总是多了一步建立缓存、删除缓存的操作上了
总的来说查询缓存这步操作弊大于利,所以MySQL官方在8.0版本删除了查询缓存的功能。
分析器
来到这一层,MySQL先通过词法分析知道要去哪张表进行操作、是‘‘select’’、“update”还是其它,也就是解析每个词汇的意思;然后再进行语法分析,把每个词汇拼起来形成语句,根据语法规则检查语句是否有误,现在MySQL才刚知道你这条sql语句真正的意图。
优化器
走到这MySQL会选择一种效率最高的查询方案,最有力的就是是否要走索引的例子;浅谈Mysql的查询过程与执行流程无索引状态查询数据:浅谈Mysql的查询过程与执行流程增加索引后看一下查询的效果:浅谈Mysql的查询过程与执行流程增加索引后明显的看出来优化器选择了查询效率最高的方法,来帮助我们查找想要的结果集;所以合理的建立索引是会助优化器一臂之力的。“什么,你问我什么是索引?下一篇咱们就扯一扯如何使用索引加速你的语句查询,请监督我”。
执行器
到这一步,就相当于你已经从小区门口走到了你的单元楼下,你还是得需要拿出门禁卡,刷一下才能有权限进入楼层,MySQL会再次检验下你是否有执行这张表的权限;现在已经知道你要查询什么,怎么在当前条件下效率最高,接下来就是调用存储引擎的接口来执行具体的查询命令(存储引擎有哪些?不同的存储引擎有哪些区别,这又是一处探讨的知识点,留下标记,监督我),没有索引的表,从读取表里面所有的数据,一行行的进行是否满足条件判断,满足条件的则会加入到结果集当中去;对于那些建立索引的并且命中的查询语句,就可以从满足条件的数据里面进行判断加入到数据集中(神马?怎么查看语句是否走索引了你都不知道,好吧,下次给你介绍如何用“神器”Explain给你的语句做一次全面体检),这个时候就可以拿着结果集给客户端了。
说完了查询流程,再battle下你的update语句,看看这个过程究竟发生了什么。
浅谈Mysql的查询过程与执行流程
缓存池(Buffer pool)
我们知道Mysql存储的数据最终是要以“页”的形式落地到磁盘中的,但是如果每次访问数据时都要从磁盘中重新读取的话效率是非常慢的;对于访问量大的程序来说是扛不住的,所以聪明的开发人员设计出缓存池的这么一个东西,因为缓存池是存放在内存中的,访问速度会大大的提高。

查询缓存池 (Query Buffer)
先说流程,数据在磁盘中都是以“页”的形式储存,每次查询时先去中检查该数据所在的页是否在缓存池中,在的话直接返回结果集,若不存在的话就要到磁盘中读取该数据的数据页以及相邻的数据页(因为Mysql会觉得你可能还会查询本数据表的其他数据,预先加载点相邻的数据页到缓存池中,下次能用到的话可以直接内存查询),然后先加载内存的缓存池中,再返回结果集。

更新缓存池(Change Buffer)
每次修改请求不是直接操作磁盘里面的数据,而是先更新缓存池里面的数据,下次有读取该数据的请求时,直接读这里面的就好了,不必再去磁盘里面做查询。但是这样会导致缓存池里面的数据和磁盘中的数据不一致,产生了脏数据的情况,别着急接下来给你唠一唠Mysql是怎么解决这问题的

浅谈Mysql的查询过程与执行流程

先介绍两个日志模块:binlog、redolog这里只是简单了解,后期会细讲mysql里面的日志
举例介绍下两个日志的配合过程:

  1. 快递员取到货物后会记录一条货物配送中的记录 = 我们这里把它比作redolog的prepare状态
  2. 快递员送到收货人手中并签字 = 产生binlog记录
  3. 快递员拿着签字单点击完成订单 = 比作redolog的commit状态表示交易完成

日志区别:
binlog 是mysql默认自带的日志,所有的存储引擎都可以使用,在的service层实现记录日志,binlog里面记录的是逻辑日志,比如update a=b ,主要用于数据备份和主从复制上
redolog 是InnoDB自带的日志,用于保证事务的实现(还有个重要日志也是用于事务,大家知道是那个日志的名字吗?)这里面记录的物理日志,比如说值a=b ,那记录的就是次条记录等于b
binlog是追加写入文件的,而redolog是特定大小的空间里面写,边写完正常提交完后后续就会消除,不是永久记录的
为什么分两个阶段提交?
先提交binlog 再提交redolog,就比如快递员先给把货物给了收货人,但是此时快递员的系统送单信息一直记录失败,系统里面并没有配送成功,这样快递公司无法查证,产生不必要的纠纷。当系统中只有binglog,由于发生问题,redolog提交失败,会导致redolog未提交,内存中的值还是a,但是数据备份或者主从是,会读取binlog里面的内容,导致主库和其他库数据不一致
先提交redolog再提交binlog,快递员自己提前在系统里面把送货订单点击完成,但是由于其他原因导致送货超时或者送货失败,这时用户和快递公司在系统里面看到订单已经完成但是收货人却未收到真正的快递,导致主库中数据值已经是b,但是binlog丢失,备份和主从的时候就会少一条记录,也会导致数据的不一致。
所以说搞个两阶段提交也是非常有必要的,有人此时会说只用一条日志记录不行吗?
使用者不同:因为binlog是Mysql自带的,所有的存储引擎都能用,但是redolog只有InnoDB引擎才有的,这就是为什么MyIsAm不支持事物而InnoDB能够支持事务的重要原因之一
用途不同:binlog是用来备份数据已经主从复制的场景,数据会一直存放;redo是在一个文件中循环写入的,这一事务提交完后后续可能就会被抹除掉了
好了!装X结束,我望着雷神Z迷茫的眼神,我坚信,当他读完我这篇文章拿起鼠标点击了一键三联的时候,代表他真的懂了
最后,非常感谢大家的耐心的阅读,新手写作,若文中发现错误还请多多指正!感谢

上一篇:MySQL架构理解


下一篇:MySQL实战第二课