一条SQL语句在MySQL中是如何执行的

发布时间:2021-11-29 15:45:02 作者:柒染
来源:亿速云 阅读:117

今天就跟大家聊聊有关一条SQL语句在MySQL中是如何执行的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

前言

最近开始在学习mysql相关知识,自己根据学到的知识点,根据自己的理解整理分享出来,小编会分析下一个sql语句在mysql中的执行流程,包括sql的查询在mysql内部会怎么流转,sql语句的更新是怎么完成的。在分析之前我会先带着你看看  MySQL 的基础架构,知道了 MySQL 由那些组件组成已经这些组件的作用是什么,可以帮助我们理解和解决这些问题。

一、mysql架构分析

下面是mysql的一个简要架构图:

一条SQL语句在MySQL中是如何执行的

mysql主要分为Server层和存储引擎层

Server层:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块  binglog日志模块。

存储引擎:  主要负责数据的存储和读取,采用可以替换的插件式架构,支持InnoDB、MyISAM、Memory等多个存储引擎,其中InnoDB引擎有自有的日志模块redolog  模块。

InnoDB 5.5.5版本作为默认引擎。

连接器

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

查询缓存

连接建立后,执行查询语句的时候,会先查询缓存,Mysql会先校验这个sql是否执行过,以Key-Value的形式缓存在内存中,Key是查询预计,Value是结果集。如果缓存key被***,就会直接返回给客户端,如果没有***,就会执行后续的操作,完成后也会把结果缓存起来,方便下一次调用。当然在真正执行缓存查询的时候还是会校验用户的权限,是否有该表的查询条件。

Mysql  查询不建议使用缓存,因为对于经常更新的数据来说,缓存的有效时间太短了,往往带来的效果并不好,对于不经常更新的数据来说,使用缓存还是可以的,Mysql 8.0  版本后删除了缓存的功能,官方也是认为该功能在实际的应用场景比较少,所以干脆直接删掉了。

分析器

mysql 没有***缓存,那么就会进入分析器,分析器主要是用来分析SQL语句是来干嘛的,分析器也会分为几步:

完成这2步之后,mysql就准备开始执行了,但是如何执行,怎么执行是***的结果呢?这个时候就需要优化器上场了。

优化器

优化器的作用就是它认为的***的执行方案去执行(虽然有时候也不是***),比如多个索引的时候该如何选择索引,多表查询的时候如何选择关联顺序等。

执行器

当选择了执行方案后,mysql就准备开始执行了,首先执行前会校验该用户有没有权限,如果没有权限,就会返回错误信息,如果有权限,就会去调用引擎的接口,返回接口执行的结果。

二、语句分析

2.1 查询语句

说了以上这么多,那么究竟一条sql语句是如何执行的呢?其实我们的sql可以分为两种,一种是查询,一种是更新(增加,更新,删除)。我们先分析下查询语句,语句如下:

select * from tb_student  A where A.age='18' and A.name='张三';

结合上面的说明,我们分析下这个语句的执行流程:

先检查该语句是否有权限,如果没有权限,直接返回错误信息,如果有权限,在mysql8.0版本以前,会先查询缓存,以这条sql语句为key在内存中查询是否有结果,如果有直接缓存,如果没有,执行下一步。

通过分析器进行词法分析,提取sql语句的关键元素,比如提取上面这个语句是查询select,提取需要查询的表名为tb_student,需要查询所有的列,查询条件是这个表的id='1'。然后判断这个sql语句是否有语法错误,比如关键词是否正确等等,如果检查没问题就执行下一步。

接下来就是优化器进行确定执行方案,上面的sql语句,可以有两种执行方案:

那么优化器根据自己的优化算法进行选择执行效率***的一个方案(优化器认为,有时候不一定***)。那么确认了执行计划后就准备开始执行了。

进行权限校验,如果没有权限就会返回错误信息,如果有权限就会调用数据库引擎接口,返回引擎的执行结果。

2.2 更新语句

以上就是一条查询sql的执行流程,那么接下来我们看看一条更新语句如何执行的呢?sql语句如下:

update tb_student A set A.age='19' where A.name='张三';

我们来给张三修改下年龄,在实际数据库肯定不会设置年龄这个字段的,不然要被技术负责人打的。其实条语句也基本上会沿着上一个查询的流程走,只不过执行更新的时候肯定要记录日志啦,这就会引入日志模块了,mysql  自带的日志模块式binlog(归档日志),所有的存储引擎都可以使用,我们常用的InnoDB引擎还自带了一个日志模块redo  log,我们就以InnoDB模式下来探讨这个语句的执行流程。流程如下:

先查询到张三这一条数据,如果有缓存,也是会用到缓存。

然后拿到查询的语句,把 age 改为19,然后调用引擎API接口,写入这一行数据,InnoDB引擎把数据保存在内存中,同时记录redo  log,此时redo log进入prepare状态,然后告诉执行器,执行完成了,随时可以提交。

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

更新完成。

这里肯定有同学会问,为什么要用两个日志模块,用一个日志模块不行吗?这就是之前mysql的模式了,MyISAM引擎是没有redo  log的,那么我们知道它是不支持事务的,所以并不是说只用一个日志模块不可以,只是InnoDB引擎就是通过redo  log来支持事务的。那么,又会有同学问,我用两个日志模块,但是不要这么复杂行不行,为什么redo log  要引入prepare预提交状态?这里我们用反证法来说明下为什么要这么做?

如果采用redo log 两阶段提交的方式就不一样了,写完binglog后,然后再提交redo  log就会防止出现上述的问题,从而保证了数据的一致性。那么问题来了,有没有一个极端的情况呢?假设redo log  处于预提交状态,binglog也已经写完了,这个时候发生了异常重启会怎么样呢?这个就要依赖于mysql的处理机制了,mysql的处理过程如下:

这样就解决了数据一致性的问题。

三、总结

  1. Mysql  主要分为Server曾和引擎层,Server层主要包括连接器、查询缓存、分析器、优化器、执行器,同时还有一个日志模块(binlog),这个日志模块所有执行引擎都可以共用。

  2. 引擎层是插件式的,目前主要包括,MyISAM,InnoDB,Memory等。

  3. 查询语句的执行流程如下:权限校验(如果***缓存)---》查询缓存---》分析器---》优化器---》权限校验---》执行器---》引擎

  4. 更新语句执行流程如下:分析器----》权限校验----》执行器---》引擎---redo log(prepare 状态---》binlog---》redo  log(commit状态)

看完上述内容,你们对一条SQL语句在MySQL中是如何执行的有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。

推荐阅读:
  1. MySQL在执行过程实现加锁与一条sql语句有什么关联
  2. sql语句在mysql中是怎么执行的

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

sql mysql

上一篇:git如何清除commit

下一篇:C/C++ Qt TreeWidget单层树形组件怎么应用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》