一条SQL语句在MySQL中是如何执行的
来源:脚本之家
时间:2022-12-31 16:42:36 307浏览 收藏
怎么入门数据库编程?需要学习哪些知识点?这是新手们刚接触编程时常见的问题;下面golang学习网就来给大家整理分享一些知识点,希望能够给初学者一些帮助。本篇文章就来介绍《一条SQL语句在MySQL中是如何执行的》,涉及到SQL语句、Mysql执行,有需要的可以收藏一下
一、mysql架构分析
下面是mysql的一个简要架构图:
mysql
主要分为Server
层和存储引擎层
Server层:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binglog
日志模块。
存储引擎: 主要负责数据的存储和读取,采用可以替换的插件式架构,支持InnoDB
、MyISAM
、Memory
等多个存储引擎,其中InnoDB引擎有自有的日志模块redolog
模块。
InnoDB 5.5.5版本作为默认引擎。
1.1 连接器
主要负责用户登录数据库,进行用户的身份认证,包括校验账户密码,权限等操作,如果用户账户密码已通过,连接器会到权限表中查询该用户的所有权限,之后在这个连接里的权限逻辑判断都是会依赖此时读取到的权限数据,也就是说,后续只要这个连接不断开,即时管理员修改了该用户的权限,该用户也是不受影响的。
1.2 查询缓存
连接建立后,执行查询语句的时候,会先查询缓存,Mysql会先校验这个sql是否执行过,以Key-Value
的形式缓存在内存中,Key是查询预计,Value
是结果集。如果缓存key被命中,就会直接返回给客户端,如果没有命中,就会执行后续的操作,完成后也会把结果缓存起来,方便下一次调用。当然在真正执行缓存查询的时候还是会校验用户的权限,是否有该表的查询条件。
Mysql 查询不建议使用缓存,因为对于经常更新的数据来说,缓存的有效时间太短了,往往带来的效果并不好,对于不经常更新的数据来说,使用缓存还是可以的,Mysql 8.0 版本后删除了缓存的功能,官方也是认为该功能在实际的应用场景比较少,所以干脆直接删掉了。
1.3 分析器
mysql
没有命中缓存,那么就会进入分析器,分析器主要是用来分析SQL语句是来干嘛的,分析器也会分为几步:
第一步,词法分析,一条SQL语句有多个字符串组成,首先要提取关键字,比如select
,提出查询的表,提出字段名,提出查询条件等等。做完这些操作后,就会进入第二步。
第二步,语法分析,主要就是判断你输入的sql是否正确,是否符合mysql的语法。
完成这2步之后,mysql就准备开始执行了,但是如何执行,怎么执行是最好的结果呢?这个时候就需要优化器上场了。
1.4 优化器
优化器的作用就是它认为的最优的执行方案去执行(虽然有时候也不是最优),比如多个索引的时候该如何选择索引,多表查询的时候如何选择关联顺序等。
1.5 执行器
当选择了执行方案后,mysql
就准备开始执行了,首先执行前会校验该用户有没有权限,如果没有权限,就会返回错误信息,如果有权限,就会去调用引擎的接口,返回接口执行的结果。
二、语句分析
2.1 查询语句
说了以上这么多,那么究竟一条sql语句是如何执行的呢?其实我们的sql可以分为2中,一种是查询,一种是更新(增加,更新,删除)。我们先分析下查询语句,语句如下:
select * from tb_student A where A.age='18' and A.name='张三';
结合上面的说明,我们分析下这个语句的执行流程:
- 先检查该语句是否有权限,如果没有权限,直接返回错误信息,如果有权限,在
mysql8.0
版本以前,会先查询缓存,以这条sql语句为key在内存中查询是否有结果,如果有直接缓存,如果没有,执行下一步。 - 通过分析器进行词法分析,提取sql语句的关键元素,比如提取上面这个语句是查询select,提取需要查询的表名为
tb_student
,需要查询所有的列,查询条件是这个表的id='1'。然后判断这个sql语句是否有语法错误,比如关键词是否正确等等,如果检查没问题就执行下一步。 - 接下来就是优化器进行确定执行方案,上面的sql语句,可以有两种执行方案:(1).先查询学生表中姓名为“张三”的学生,然后判断是否年龄是18。(2).先找出学生中年龄18岁的学生,然后再查询姓名为“张三”的学生。
- 那么优化器根据自己的优化算法进行选择执行效率最好的一个方案(优化器认为,有时候不一定最好)。那么确认了执行计划后就准备开始执行了。
- 进行权限校验,如果没有权限就会返回错误信息,如果有权限就会调用数据库引擎接口,返回引擎的执行结果。
2.2 更新语句
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 直接提交,然后写 binlog,假设写完
redo log
后,机器挂了,binlog
日志没有被写入,那么机器重启后,这台机器会通过redo log
恢复数据,但是这个时候bingog
并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。 - 先写binlog,然后写redo log,假设写完了
binlog
,机器异常重启了,由于没有redo log
,本机是无法恢复这一条记录的,但是binlog
又有记录,那么和上面同样的道理,就会产生数据不一致的情况。
如果采用redo log
两阶段提交的方式就不一样了,写完binglog
后,然后再提交redo log
就会防止出现上述的问题,从而保证了数据的一致性。那么问题来了,有没有一个极端的情况呢?假设redo log
处于预提交状态,binglog
也已经写完了,这个时候发生了异常重启会怎么样呢? 这个就要依赖于mysql
的处理机制了,mysql的处理过程如下:
- 判断
redo log
是否完整,如果判断是完整的,就立即提交。 - 如果
redo log
只是预提交但不是commit
状态,这个时候就会去判断binlog
是否完整,如果完整就提交redo log
, 不完整就回滚事务。
这样就解决了数据一致性的问题。
三、总结
Mysql
主要分为Server
曾和引擎层,Server层主要包括连接器、查询缓存、分析器、优化器、执行器,同时还有一个日志模块(binlog),这个日志模块所有执行引擎都可以共用。- 引擎层是插件式的,目前主要包括,MyISAM,InnoDB,Memory等。
- sql等执行过程分为两类,一类对于查询等过程如下:权限校验---》查询缓存---》分析器---》优化器---》权限校验---》执行器---》引擎
- 对于更新等语句执行流程如下:分析器----》权限校验----》执行器---》引擎---redo log prepare---》binlog---》redo log
commit
文中关于mysql的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《一条SQL语句在MySQL中是如何执行的》文章吧,也可关注golang学习网公众号了解相关技术文章。
-
368 收藏
-
160 收藏
-
205 收藏
-
119 收藏
-
501 收藏
-
481 收藏
-
284 收藏
-
316 收藏
-
437 收藏
-
412 收藏
-
364 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习