超详细解析:在执行一条SQL语句期间发生了什么?

目录

  • 前言
  • MySQL的执行流程
    • Server层
      • 连接器
      • 查询缓存
      • 词法分析器
      • 预处理
      • 优化器
      • 执行器
    • 引擎层
      • 具体流程
      • 为什么需要redolog
        • redolog的组成
        • redolog如何提高性能?
        • redo log与binlog区别
  • 总结

前言

我们学习MySQL时,首先第一个接触到的就是SQL语句了,那么在我们运行一条SQL语句时,在MySQL中究竟发生了什么?MySQL是如何在那么多数据中准确的找出我们要操作的那一条语句并且执行我们需要做的操作的?
为了解开这个疑问,我们就从MySQL的内部“零件”开始看起吧~

MySQL的执行流程

MySQL内部的架构图:

在这里插入图片描述

MySQL的架构总共分为两层:Server层和存储引擎层

Server层负责建立连接,分析和执行SQL。MySQL大多数的核心功能模块都在Server层实现

Server层

存储引擎层负责数据的存储和提取,支持 InnoDB、MyISAM、Memory 等多个存储引擎,不同的存储引擎共用一个 Server 层。现在最常用的存储引擎是 InnoDB,从 MySQL 5.5 版本开始, InnoDB 成为了 MySQL 的默认存储引擎。我们常说的索引数据结构,就是由存储引擎层实现的,不同的存储引擎支持的索引类型也不相同,比如 InnoDB 支持索引类型是 B+树 ,且是默认使用,也就是说在数据表中创建的主键索引和二级索引默认使用的是 B+ 树索引。

连接器

使用MySQL的第一步一定是要先和MySQL服务建立连接,之后才能执行SQL语句。使用Windows系统连接MySQL数据库需要使用如下命令:

启动MySQL服务器:

net start mysql

打开数据库:

mysql -u root -p

然后输入用户名密码进行验证,如果用户密码都没有问题,连接器就会获取该用户的权限,然后保存起来,后续该用户在此连接里的任何操作,都会基于连接开始时读到的权限进行权限逻辑的判断。

如果连接长时间没有数据,连接器就会自动断开,时间由参数wait_timeout控制,默认为八小时

查询缓存

在MySQL8.0以下版本存在查询缓存,当我们查询一条数据库时,会将我们的查询语句以及结果以key-value键值对的形式存储到查询缓存里,如果再次查询该条语句,将会把结果直接从查询缓存里返回。

这时有的小伙伴可能会产生一些疑惑了:这么说来,如果我们对数据库中的一些数据进行了修改,再对该数据进行查询,那我们查询到的数据岂不是在查询缓存之中拿到的之前查询到的值吗?这样还如何能确保我们拿到的数据是最新的呢?别急,查询缓存的运行机制是当有任何一条sql将表中的任一字段进行修改,那么将会把这之前的查询缓存全部清空,再重新存储。

啊这…费劲巴拉的把结果都存储起来了,结果一个更新过来,直接全部缓存清空,之前的努力全部白废掉了…鸡肋!非常的鸡肋!

因此在8.0及以后版本就删除掉了这个功能。。。

词法分析器

如果没有命中缓存,就要开始真正执行语句了。首先,MySQL需要知道你要做什么,因此需要对SQL语句做解析。

分析器首先会做“词法分析”,我们输入的SQL语句是由多个字符串和空格组成的,MySQL 会根据我们输入的字符串识别出关键字出来。

接下来要做的是语法分析。根据词法分析的结果,语法分析器会根据语法规则,判断我们输入的这个SQL语句是否满足MySQL语法。如果语句不对,就会返回一条“You hava an error in your SQLsyntax”的错误。

如果没问题就会构建出 SQL 语法树,这样方便后面模块获取 SQL 类型、表名、字段名、 where 条件等等。

在这里插入图片描述

预处理

在预处理阶段,会检查我们SQL语句中所涉及到的表或字段是否存在,并且将select * 中的 * 符号扩展为表上的所有的列

优化器

优化器主要负责将 SQL 查询语句的执行方案确定下来,比如在表里面有多个索引的时候,优化器会基于查询成本的考虑,来决定选择使用哪个索引。

要想知道优化器选择了哪个索引,我们可以在查询语句最前面加个 explain 命令,这样就会输出这条 SQL 语句的执行计划,然后执行计划中的 key 就表示执行过程中使用了哪个索引

执行器

通过执行器将最终的sql语句放到存储引擎层。

执行器会根据表的存储引擎,使用这个存储引擎提供的接口;在执行SQL语句之前执行器会先进行权限检查,确保当前用户有足够的权限执行该操作。

那么在引擎层具体会发生什么呢?我们以Innodb为例来解析一下。

引擎层

我们先看一个详细流程图。

在这里插入图片描述

具体流程

  • 数据库的增删改查都是直接操作Buffer Pool,Buffer Pool一般设置为机器内存的60%~70%左右。首先在Buffer Pool中查询是否存在该条数据,如果不存在,则会从磁盘文件(ibd)中将该条数据加载到缓存池中来。

  • 之后就是将要修改的数据的旧值放入到undolog(回滚日志文件)中,这里主要是将历史数据进行一个记录,以便于回滚。

  • 将旧数据进行一个存储后,就可以对缓存中的数据进行修改了,之后再将更新完的数据写入redolog中,redolog将顺序写入磁盘文件中去。

  • 将准备提交的数据写入binlog日志一份,binlog主要用来恢复数据库磁盘里的数据

  • 在redolog的该条数据里写入一个commit标记,写入标记后会向客户端返回事务提交成功。

  • 在系统空闲时,以page为单位随机写入磁盘

如果事务提交成功,buffer Pool里的数据还没来得及写入磁盘,此时系统宕机了,可以用redo日志里的数据恢复磁盘ibd文件里的数据

为什么需要redolog

redolog是Innodb特有的,在上面的流程中可以看出,redolog和binlog做的事情是基本相似的,那已经存在了binlog,为什么innodb又设计了redolog呢?

redolog的组成

redolog由两部分组成,一个是内存中的日志缓冲(redo log buffer),另一个是磁盘上的日志文件(redo log file)。mysql每执行一条DML语句,先将记录写入redo log buffer,后续某个时间点再一次性将多个操作记录写到redo log file。

redolog如何提高性能?

我们都知道,事务的四大特性里面有一个是持久性,具体来说就是只要事务提交成功,那么对数据库做的修改就被永久保存下来了,不可能因为任何原因再回到原来的状态。那么mysql是如何保证一致性的呢?最简单的做法是在每次事务提交的时候,将该事务涉及修改的数据页全部刷新到磁盘中。但是这么做会有严重的性能问题:

一方面,由于Inoodb是以页为单位进行磁盘交互的,而一个事务可能只修改一页数据中的某几个字节,如果每修改一次就将整个数据页刷新到磁盘一遍的话,也太浪费资源了

另一方面,idb数据文件是随机读写,不同的数据表有不一样的ibd文件,修改不同的表的话就要修改不同表的ibd文件,不能实现顺序写文件的效果,耗时非常长。而redo是一个或几个预先分配好磁盘空间的文件,写入永远都是在文件末尾追加,具体来说就是只记录事务对数据页做了哪些修改,相对而言文件更小,也可以很好的解决性能问题。

redo log与binlog区别

redo log 主要用于保证事务的持久性(Durability)。当事务提交时,redo log 会记录事务对数据库的修改操作,以保证即使在数据库崩溃的情况下,这些修改也能够被恢复。

binlog 用于记录数据库的所有更改操作,包括对数据的增删改操作以及对数据库结构的修改;与 redo log 不同,binlog 的写入是按照事务的提交顺序进行的,而不是按照数据修改的顺序。

总结

看了这么多了,那我们来总结一下,在执行一条SQL语句期间发生了什么?

  1. 连接器:建立连接,校验用户身份;
  2. 查询缓存:直接将SQL语句与查询缓存中的所有键值对进行比对,如果命中缓存则直接返回结果,如果没有则继续向下执行,在查询到结果时存储到查询缓存中一份;MySQL8.0及以后版本废除;
  3. 解析SQL:通过解析器对 SQL 查询语句进行词法分析、语法分析,然后构建语法树;
  4. 执行SQL:先经过预处理和优化,再通过执行器调用引擎接口
  5. 对数据库进行处理,返回结果。

如有其他见解,欢迎各位大佬留言讨论~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/461821.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MD5算法:密码学中的传奇

title: MD5算法:密码学中的传奇 date: 2024/3/15 20:08:07 updated: 2024/3/15 20:08:07 tags: MD5起源算法原理安全分析优缺点比较技术改进示例代码应用趋势 MD5算法起源: MD5(Message Digest Algorithm 5)算法是由MIT的计算机…

Linux之shell条件测试

华子目录 用途基本语法格式示例 文件测试参数示例 整数测试作用操作符示例~:检查左侧内容是否匹配右侧的正则表达式 案例分析逻辑操作符符号示例 命令分隔符&>:不管成功与否,都将信息写进黑洞中 用途 为了能够正确处理shell程序运行过…

django开发流式格式后的在nginx的部署的记录

关键记录. django上传代码要导出配置 pip freeze > requirements.txt 这个很关键。后面部署直接读取的 关键记录. django上传代码要导出配置 pip freeze > requirements.txt 这个很关键。后面部署直接读取的 关键记录. django上传代码要导出配置 pip freeze > require…

Python 基础语法:基本数据类型(字典)

为什么这个基本的数据类型被称作字典呢?这个是因为字典这种基本数据类型的一些行为和我们日常的查字典过程非常相似。 通过汉语字典查找汉字,首先需要确定这个汉字的首字母,然后再通过这个首字母找到我们所想要的汉字。这个过程其实就代表了…

Unity的AssetBundle资源运行内存管理的再次深入思考

大家好,我是阿赵。   这篇文章我想写了很久,是关于Unity项目使用AssetBundle加载资源时的内存管理的。这篇文章不会分享代码,只是分享思路,思路不一定正确,欢迎讨论。   对于Unity引擎的资源内存管理,我…

调皮的String及多种玩法(下部)

👨‍💻作者简介:👨🏻‍🎓告别,今天 📔高质量专栏 :☕java趣味之旅 欢迎🙏点赞🗣️评论📥收藏💓关注 💖衷心的希…

0101插入排序-算法基础-算法导论第三版

文章目录 一 插入排序二 循环不变式与插入排序的正确性三 伪代码中的一些约定四 Java代码实现插入排序结语 一 插入排序 输入: n n n个数订单一个序列 ( a 1 , a 2 , ⋯ , a n ) (a_1,a_2,\cdots,a_n) (a1​,a2​,⋯,an​). **输出:**输入序列的一个排…

【how2j练习题】HTML部分综合练习

练习题 1 <html><h1>英雄联盟 &#xff08;电子竞技类游戏&#xff09;</h1> <p> <strong>《英雄联盟》</strong>&#xff08;简称lol&#xff09;是由美国<i>Riot Games</i>开发&#xff0c;中国大陆地区由腾讯游戏运营的网络…

openGauss学习笔记-244 openGauss性能调优-SQL调优-典型SQL调优点-统计信息调优

文章目录 openGauss学习笔记-244 openGauss性能调优-SQL调优-典型SQL调优点-统计信息调优244.1 统计信息调优244.1.1 统计信息调优介绍244.1.2 实例分析&#xff1a;未收集统计信息导致查询性能差 openGauss学习笔记-244 openGauss性能调优-SQL调优-典型SQL调优点-统计信息调优…

4.10.CVAT——3D对象标注

文章目录 1. 创建任务2. 3D 任务工作区3.标准 3D 模式 Standard 3D mode4. 用长方体进行注释4.1. 用shapes进行注释4.2. 使用长方体进行跟踪Tracking 使用 3D 注释工具来标记 3D 对象和场景&#xff0c;例如车辆、建筑物、景观等。 1. 创建任务 要创建 3D 任务&#xff0c;您必…

快速从0-1完成聊天室开发——环信ChatroomUIKit功能详解

聊天室是当下泛娱乐社交应用中最经典的玩法&#xff0c;通过调用环信的 IM SDK 接口&#xff0c;可以快速创建聊天室。如果想根据自己业务需求对聊天室应用的 UI界面、弹幕消息、礼物打赏系统等进行自定义设计&#xff0c;最高效的方式则是使用环信的 ChatroomUIKit 。 文档地址…

面试题手撕篇

参考博客 开始之前&#xff0c;理解递归 手写 浅拷贝 function shallow(target){if(target instanceof Array){return [...resObj]}else{return Object.assign({},target);} }手写深拷贝 const _sampleDeepClone target > {// 补全代码return JSON.parse(JSON.stringify…

mybatis源码阅读系列(一)

源码下载 mybatis 初识mybatis MyBatis 是一个优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解用于配置和原始映射&#xff0c;将接口和 Java 的…

UE4_调试工具_绘制调试球体

学习笔记&#xff0c;仅供参考&#xff01; 效果&#xff1a; 步骤&#xff1a; 睁开眼睛就是该变量在此蓝图的实例上可公开编辑。 勾选效果&#xff1a;

【小白刷leetcode】第15题

【小白刷leetcode】第15题 动手刷leetcode&#xff0c;正在准备蓝桥&#xff0c;但是本人算法能力一直是硬伤。。。所以做得一直很痛苦。但是不熟练的事情像练吉他一样&#xff0c;就需要慢速&#xff0c;多练。 题目描述 看这个题目&#xff0c;说实在看的不是很懂。索性我们直…

GUROBI建模之非线性约束的处理

官方文档 目录 官方文档&#xff1a;GRBModel.AddGenConstrXxx() - Gurobi Optimization 数学规划的约束类型 基本约束(fundamental constraints)&#xff1a; 通用约束(general constraints): 1. GUROBI求解器有针对这类约束的函数&#xff0c;直接调用这类函数即可 2.…

Python-GIS分析之地理数据空间聚类

地理空间数据聚类是空间分析和地理信息系统(GIS)领域的一项关键技术。这种方法对于理解地理数据固有的空间模式和结构、促进城市规划、环境管理、交通和公共卫生等各个领域的决策过程至关重要。本文探讨了地理空间数据聚类的概念、方法、应用、挑战和未来方向。 当模式出现…

音频切割如何操作?剪辑音乐入门教程

随着数字音乐时代的来临&#xff0c;音频编辑和音乐剪辑成为了越来越多人的必备技能。无论是想要制作个人音乐作品&#xff0c;还是想要为视频添加背景音乐&#xff0c;了解如何切割和剪辑音频都是非常重要的。本文将为你提供一份音频切割和音乐剪辑的入门教程&#xff0c;帮助…

13-操作符(初识)

课前小技巧&#xff1a;VS中&#xff0c;想要复制哪一行&#xff0c;直接把鼠标放在哪一行&#xff0c;CtrlC即可&#xff0c;CtrlV直接自动复制到下一行 C语言非常灵活&#xff1a;C语言提供了非常丰富的操作符&#xff0c;使用起来比较灵活 13-1 算术操作符 - * / % 这…

WXML 模板语法

数据绑定 1. 数据绑定的基本原则 ① 在 data 中定义数据 在页面对应的 .js 文件中&#xff0c;把数据定义到 data 对象中即可 ② 在 WXML 中使用数据 2. Mustache 语法的格式 把 data 中的数据绑定到页面中渲染&#xff0c;使用 Mustache 语法&#xff08;双大括号&#x…
最新文章