一条sql语句在MySQL中的执行过程

Write in first

平常我们经常写sql语句,但是sql语句在数据库中的执行过程又是啥样呢?本文就从数据库的基本架构与sql语句的类型两方面来分析下sql语句的执行过程。

因为本文主要涉及MySQL数据库中sql语句的执行过程,所以你要是关心像oracle、sql server等数据库的话,可能不太适用(因为我也没用过oracle。。。)。

基本架构

MySQL可以分为server层与存储引擎两个部分。

server层:连接器、查询缓存、分析器、优化器、执行器等都是属于server层的。这些部件可以对我们的sql语句进行检验、优化等等。

存储引擎的作用就是负责数据的存储和读取,像常见的存储引擎有 InnoDB、MyISAM等。其中 InnoDB 引擎自带了日志模块 redolog 模块。现在最常用的存储引擎是 InnoDB,而且从 MySQL 5.5 版本开始就被当做默认存储引擎了。关于存储引擎有兴趣的可以看下我的这篇文章:InnoDB与MyISAM的多种区别与选择

还是画个图简单表示一下吧:
在这里插入图片描述你这图也太简单了吧!

毕竟只是展示下整体的流程嘛,接下来才具体介绍每个部分嘛。

server层

既然上面说了serve层有连接器、查询缓存、分析器、优化器、执行器这些部分,那我们就来看下这些都是干啥的。

连接器:连接器的功能就是与身份认证和权限相关的。当用户登录数据库的时候,连接器会进行用户的身份认证,包括像账号密码的验证,权限验证等等,如果用户账户密码已通过,连接器会到权限表中查询该用户的所有权限,之后在这个连接里的权限逻辑判断都是会依赖此时读取到的权限数据,也就是说,后续只要这个连接不断开,即时管理员修改了该用户的权限,该用户也是不受影响的。

查询缓存:查询缓存主要是涉及SELECT 语句部分的。当执行SELECT 语句的时候,他会先查询MySQL中的缓存中有没有要查询的数据,如果缓存中有,那么就直接返回缓存中的内容。如果没有,那么在sql语句执行完毕之后,会将查询的结果以key-value的形式缓存下来,当以后相同的语句执行的时候,就可以直接返回缓存中的内容。

这怎么和我们使用Redis的场景很像呢?可惜啊,MySQL查询是不建议使用缓存的。你想啊,在MySQL中,我们大部分表中的值是更新的比较频繁的,一旦表中的值改变了,那么对应的缓存也要改变。缓存的修改过于频繁,对于数据库也是一种负担。因此在MySQL8.0版本的时候就将缓存的功能删除掉了。

分析器:MySQL 没有命中缓存,那么就会进入分析器,分析器主要是用来分析sql语句有哪些关键部分、这条sql语句是干啥的,分析器的执行可以分为两步:

第一步,词法分析:这一步分析器会找出sql语句中的关键词,比如像select啦、表名啦、查询条件等等(貌似sql语句就这些吧。。。)。

第二步,语法分析:这一步主要就是判断sql语句是否合法,有没有啥毛病。如果都没问题,那么就该我们的优化器来接力了。

优化器:不知道你是不是知道在JVM执行我们代码的时候,会对代码进行指令重排序。JVM会在不改变程序的执行结果的情况下,将程序按照JVM的意愿来进行重排序,目的就是为了更高的执行效率。MySQL也是如此,他会以不改变sql语句的执行结果为前提,找到他自己认为最高效的执行顺序。

什么?你觉得你写的sql语句才是跑的最快的?MySQL:我不要你觉得,我要我觉得。

执行器:当上面的步骤执行完之后,基本就已经尘埃落定了。此时MySQL会开始准备执行sql语句,去调用对应的存储引擎。

sql语句分析

说了这么多,总算到了揭开sql语句执行过程的面纱了。在此sql语句可以分为两种:一种是不改变数据库数据的查询语句;一种是可以改变数据库数据的语句(增加、删除、修改)。

查询语句

就以一个简单的sql语句为例:

select username,age,gender from user where age>'20' and gender='female'

找出user表中年龄大于20的女同学。

我们按照server层的几个模块来执行:

sql语句会先遇到连接器,连接器对登录人的权限进行校验,校验通过之后,如果是8.0版本之前,那么就会查询缓存,如果缓存中有,那么就将缓存中的内容返回出去,如果缓存中没有,那么就调用分析器。

分析器一方面看这条sql语句有没有问题(这条sql语句当然是没问题的),然后再找出这条sql语句中的一些关键信息,像select、user表,条件。找到之后,调用优化器,像这条语句,可以先找到年龄大于20的user,然后再找出女同学;也可以先找出女同学,然后再以年龄进行过滤,至于具体咋整,还是要看表的设计啦。

优化器执行完毕后,就确认了sql语句的执行过程,然后调用存储引擎接口执行sql语句就OK了。

修改语句

因为增加、删除、修改语句都会改变数据库中的数据,在这里,我们就以删除语句为例,看看是咋执行。

delete from user where username='雪浪风尘'

删除语句的执行过程与查询语句的过程还是有些地方不同的,

首先执行sql语句,分析器会提取sql语句中的关键词,然后再进行权限验证。如果验证通过,那么就会执行sql语句。因为select语句将数据库中的数据查询出来之后,就会返回。但是像update、delete、insert语句会更改数据库中的数据,所以就会用到日志模块了。

我们在上面看到,innoDB存储引擎有自己的日志模块的,而MySQL的默认存储引擎就是innoDB,因此我们就以innoDB引擎为例。

执行器找到我们要删除的数据,调用引擎 API 接口,同时记录 redo log(也就是innodb自带的日志),此时 redo log 进入 prepare 状态,然后告诉执行器,任务随时可以提交(也就是随时可以将数据删除)。

执行器收到通知后记录 binlog,然后调用引擎接口,innodb引擎的redo log 置为提交状态。

其实关于innodb引擎之所以能够实现事务功能,而MyIsam引擎没有事务功能,则是与这个redo log有关的。正是因为有这个redo log日志模块。innodb才能够实现事务,毕竟MySQL自带的日志模块只有归档的作用。

总结

其实我们可以看到,MySQL 主要分为 Server 层和引擎层,Server 层主要包括连接器、查询缓存、分析器、优化器、执行器,同时还有一个日志模块(binlog),这个日志模块所有执行引擎都可以共用。redolog 只有 InnoDB 有。

引擎层是插件式的,主要有MyISAM、InnoDB。

至于两种状态的执行过程,我觉得用两张图来描述就很恰当:
查询:
在这里插入图片描述
修改数据:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值