概览

  本篇文章会分析下一个sql语句在mysql中的执行流程,包括sql的查询在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语句是来干嘛的,分析器也会分为几步:

  第一步,词法分析,一条SQL语句有多个字符串组成,首先要提取关键字,比如select,提出查询的表,提出字段名,提出查询条件等等。做完这些操作后,就会进入第二步。

  第二步,语法分析,主要就是判断你输入的sql是否正确,是否符合mysql的语法。

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

  优化器

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

  执行器

  当选择了执行方案后,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语句,可以有两种执行方案:

  a.先查询学生表中姓名为“张三”的学生,然后判断是否年龄是18。 b.先找出学生中年龄18岁的学生,然后再查询姓名为“张三”的学生。

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

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

  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 直接提交,然后写 binlog,假设写完redo log 后,机器挂了,binlog日志没有被写入,那么机器重启后,这台机器会通过redo log恢复数据,但是这个时候bingog并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。

  先写binlog,然后写redo log,假设写完了binlog,机器异常重启了,由于没有redo log,本机是无法恢复这一条记录的,但是binlog又有记录,那么和上面同样的道理,就会产生数据不一致的情况。郑州不孕不育医院哪家好:www.zzchbb.com/

  如果采用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

一条SQL语句在MySQL中是如何执行的的更多相关文章

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

    一 MySQL 基础架构分析 1.1 MySQL 基本架构概览 下图是 MySQL 的一个简要架构图,从下图你可以很清晰的看到用户的 SQL 语句在 MySQL 内部是如何执行的. 先简单介绍一下下图 ...

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

    本篇文章会分析一个 sql 语句在 MySQL 中的执行流程,包括 sql 的查询在 MySQL 内部会怎么流转,sql 语句的更新是怎么完成的. 在分析之前我会先带着你看看 MySQL 的基础架构, ...

  3. 一条查询语句在MySQL中是如何执行的?

    前言 我们在学习一种技术的时候,首先要鸟瞰其全貌,千万不要一开始就陷入到细节中去,这样有助于我们站在高维度其理解问题 —— 丁奇. 学习MySQL也是一样,所以我们可以从一条查询语句的执行开始看起. ...

  4. 原来select语句在MySQL中是这样执行的!看完又涨见识了!这回我要碾压面试官!

    大家好,我是冰河~~ MySQL作为互联网行业使用最多的关系型数据库之一,与其免费.开源的特性是密不可分的.然而,很多小伙伴工作了很多年,只知道使用MySQL进行CRUD操作,这也导致很多小伙伴工作多 ...

  5. 使用PowerDesigner创建物理模型并生成SQL语句在MySQL中生成表

    我使用的PowerDesigner的版本为16.5,创建物理模型后,使用PowerDesigner生成的SQL语句,在MySQL中创建表. 1. 打开Power Designer软件,在弹出的欢迎对话 ...

  6. sql语句(mysql中json_contains、json_array的使用)

    https://blog.csdn.net/qq_35952946/article/details/79131488 https://www.jianshu.com/p/455d3d4922e1 1. ...

  7. SQL语句在数据库中是如何执行的

    第一步:应用程序把查询SQL语句发给服务器端执行 我们在数据层执行SQL语句时,应用程序会连接到相应的数据库服务器,把SQL语句发送给服务器处理. 第二步:服务器解析请求的SQL语句 SQL计划缓存, ...

  8. 一条sql语句引发mysql不停创建临时表的问题解决..coping to tmp table on desk

    (不懂临时表的先看 MySQL临时表 ) 首先,临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间.因此在不同的连接中可以创建同名的临时表,并且操作属于本连接的临时表.     ...

  9. sql语句在Mysql中如何执行?

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

随机推荐

  1. 发送邮件小工具(python)

    #!/usr/bin/python # -*- coding:UTF- -*- import sys import smtplib import email.mime.multipart import ...

  2. HDU - 4006 The kth great number multiset应用(找第k大值)

    The kth great number Xiao Ming and Xiao Bao are playing a simple Numbers game. In a round Xiao Ming ...

  3. Python3.6 的字符串内建函数

    1.capitalize(self) 将字符串的第一个字符转换为大写 2.casefold(self) 返回将字符串中所有大写字符转换为小写后生成的字符串 3.center(self, width, ...

  4. E20190225-hm

    seal  n. 密封; 印章; 海豹; 封条;   v. 密封; 盖章; 决定; 封上(信封); primitive adj. 原始的; 发展水平低的; 落后的; [生物学] 原生的;  n. 原始 ...

  5. TP5之上传多张图片

    1.效果图(每点击一次‘添加选项’,就会有一个新的 file 框来添加新的图片) 2.view <!--不要忘了引入jquery文件--> <!-- post传值方式和文件传输协议一 ...

  6. Qt 生成word、pdf文档

    需求:将软件处理的结果保存为一个报告文档,文档中包含表格.图片.文字,格式为word的.doc和.pdf.生成word是为了便于用户编辑. 开发环境:qt4.8.4+vs2010 在qt的官网上对于p ...

  7. LightOJ 1029 【最小生成树】

    思路: 利用克鲁斯卡尔算法,最小生成树把边从小到大排序,然后Union: 最大生成树就是把边从大到小排序,然后Union: #include<bits/stdc++.h> using na ...

  8. 3DMAX 烘培技术

    烘培是指,把光照信息渲染成贴图,而后把这个烘培后的贴图再贴回到场景中去的技术.烘培技术把光照计算的结果提前写入到了贴图中,因此在实时渲染中不需要进行耗时的光照计算,大大提高了实时渲染的效率. 烘培和渲 ...

  9. nmon性能监控工具学习

    nmon在AIX环境上,是一款很出名的系统性能监控工具,其实它除了可以运行在AIX,还可以在Linux环境下编译.使用. 源码下载地址: http://nmon.sourceforge.net/pmw ...

  10. springboot2.x 的 RedisCacheManager变化

    springboot2.x 的 RedisCacheManager变化 springboot2.x 的 RedisCacheManager变化 由于最近在学着使用redis做缓存,使用的是spring ...