SQL底层执行过程

MySQL 的查询流程

  • 客户端请求
  • 连接器

负责与客户端的通信,是半双工模式(半双工(Half Duplex)数据传输指数据可以在一个信号载体的两个方向上传输,但是不能同时传输。),验证请求用户的账户和密码是否正确,③如果用户的账户和密码验证通过,会在MySQL自带的权限表中查询当前用户的权限:

验证用户身份,给予权限

  • 查询缓存

MySQL的缓存主要的作用是为了提升查询的效率,缓存以key和value的哈希表形式存储,key是具体的sql语句,value是结果的集合。如果无法命中缓存,就继续走到分析器的的一步,如果命中缓存就直接返回给客户端 。(存在缓存则直接返回,不存在则执行后续操作

  • 分析器

分析器的主要作用是将客户端发过来的sql语句进行分析,这将包括预处理与解析过程,在这个阶段会解析sql语句的语义,并进行关键词和非关键词进行提取、解析,并组成一个解析树。具体的关键词包括不限定于以下:select/update/delete/or/in/where/group by/having/count/limit等.如果分析到语法错误,会直接给客户端抛出异常:ERROR:You have an error in your SQL syntax.(对SQL进行词法分析和语法分析操作)

  • 优化器

主要对执行的sql优化选择,最优的执行方案方法(判断走哪个索引)

  • 执行器

执行时会先看用户是否有执行权限,有才去使用这个引擎提供的接口

  • 去引擎层获取数据返回

如果开启查询缓存则会缓存查询结果

在mysql8.0后,放弃缓存机制。原因在于:如果对表数据进行表更新操作某一条数据,无法查找那条已缓存的数据进行并进行更改,而是对更新操作对那张表所有缓存数据进行清空

SQL在引擎层执行过程(INNODB引擎)

在掌握SQL在引擎层的执行过程,首先需要掌握以下几个知识点

缓存池(Buffer Pool)

数据库的CURD操作都是直接操作Buffer Pool,默认大小128M,一般设置为机器内存的60%~70%。

缓存池数据结构= 描述信息(数据页的元数据信息,包括数据页所属表空间、数据页编号)+缓存页

InnoDB的缓冲池设计的思路 
  • 磁盘访问按页读取能够提高性能,所以缓冲池一般也是按页缓存数据;
  • 预读机制启示了我们,能把一些“可能要访问”的页提前加入缓冲池,避免未来的磁盘IO操作;
Buffer Pool中哪些是空闲的缓存页

MYSQL引入了一个链表来帮助我们找到空闲的缓存页,叫free链表,是一个双向链表,链表节点是空闲的缓存页对应的描述信息块(空的缓存页)。

free加载的时机:数据库启动时,如果缓存页不够用了

如何数据是否在Buffer Pool中(查询)

MYSQL中还有一个哈希表数据结构,用表空间号+数据页号作为key,缓存页的地址作为value。当需要操作数据页时,首先从哈希表中根据"表空间号+数据页号"作为key进行查询,如果查询不为空的话证明数据页已经被缓存了;如果查询为空,则从磁盘进行加载,并将数据写入该哈希表,下次再使用这个数据页,就可直接从哈希表中读取。

更新Buffer Pool中的数据

当我们对数据进行更新操作时,由于是直接操作Buffer Pool缓存中的数据,势必会导致和磁盘文件中的数据页不一致,这些不一致的数据页就叫脏页

脏页是需要刷盘的,那刷盘的时候怎么知道哪些数据页需要刷,哪些不需要刷呢?因为不可能每个数据页都刷一遍,这样效率太低了。

解决脏页的方案:MYSQL引入了另一个链表来记录更新过的脏页数据,叫flush链表。通过这个flush链表,就能记录目前哪些缓存页是脏页,刷盘的时候后台线程只需要处理这个链表上面记录的数据页即可,刷盘结束后,将节点从链表上抹去。

Buffer Pool内存空间不足

基于LRU算法淘汰Buffer Pool内部缓存页,缓存命中率低的缓存页会被淘汰。引入一个新的LRU链表来记录,缓存页的命中情况(最新访问的缓存页一定在LRU头部,链表尾巴的肯定是命中率比较低的,需要被淘汰)

  • 普通LRU有什么问题

容易出现预读失效 预读:由于预读(Read-Ahead),提前把页放入了缓冲池,但最终MySQL并没有从页中读取数据,称为预读失效。

容易出现缓冲池污染 缓冲池污染:当某一个SQL语句,要批量扫描大量数据时,可能导致把缓冲池的所有页都替换出去,导致大量热数据被换出,MySQL性能急剧下降,这种情况叫缓冲池污染。 eg: select * from user where name like "%shenjian%"; 虽然结果集可能只有少量数据,但这类like不能命中索引,必须全表扫描,就需要访问大量的页。

  • MYSQL对LRU算法进行的优化
  • 冷热数据分离,可以将LRU链表分为两个,一个存放冷数据,一个存放热数据

回滚日志(undo日志)

回滚日志,保存了事务发生之前的数据的一个版本,用于事务的回滚操作。

  • 事务发生错误时回滚rollback,数据更新之前,会把原始数据保存在回滚日志中,保证事务出错回滚或者我们手动回滚的时候,能够在回滚日志中找到最初的数据。
  • 提供了MVCC的非锁定读(快照读),依赖undo log实现。

重做日志(redo 日志)

redo 日志是为了在系统因奔溃而重启时恢复奔溃前的状态而提出的。lnnoDB 存储引擎是以页为单位来管理存储空间的,我们进行的增删改查操作从本质上来说都是在访问页面(包括读页面、写页面、创建),其实都在缓存池中操作。如果系统崩溃,可以通过该日志将数据加载到磁盘中,确保缓存池的数据和磁盘数据保持一致(redo 日志是用来保证 MySQL 持久化功能的)。

二进制日志(binlog日志 )

Bin Log是一个二进制格式的文件,是MySQL最重要的日志,它记录了所有的DDL及DML语句(除了数据查询select、show等),以事件形式记录,还包含语句所执行的消耗时间,MySQL的二进制日志是事务安全型的。binlog 的主要目的是复制和恢复(mysqlbinlog来恢复

错误日志(error日志)

记录中MySQL启动和关闭服务的时候详细的日志信息,包括在MySQL实例在运行过程中遇到的错误、警告等信息也会记录在error log中。

SQL在引擎层执行步骤

以update 语句为例:update table set name="123" where id = 666

  • 第一步

首先先判断数据是否在Buffer Pool的页中,如果不在,加载id为666的数据所在的缓存页加载到Buffer pool中。

  • 第二步

写入更新数据前的旧数据到undo日志中

  • 第三步

Buffer Pool中对数据进行更新操作

  • 第四步

写redo日志(在哪页做了修改),redo日志顺序写入磁盘,准备提交事务(prepare阶段)

  • 第五步

准备提交事务,binlog日志写入磁盘中

  • 第六步

写commit标记事务到redo日志中,保证redo日志和binlog日志保持一致

  • 第七步

在系统空闲,将数据写入磁盘中,以页的形式


Redolog和binlog区别

redolog是循环写的,空间固定会用完;binlog是可以追加写的

redolog是InnoDB存储引擎特有的日志,用于记录事务的操作,包括对数据的修改、插入和删除等。redolog是在内存中缓存的,当事务提交时,会将redolog写入磁盘中的redo log文件中,以保证数据的持久性。

binlog是MySQL服务器的日志,用于记录所有的数据库操作,包括对数据的修改、插入和删除等。binlog是在磁盘上的文件,可以用于数据备份、恢复和复制等操作。

mysql redo log为什么有两阶段提交/为什么有prepare和commit两个状态

为了解决redo log和binlog不一致的问题。

我们直接提交事务,直接写入redo不可以吗,为什么要设置两阶段提交的机制呢?
这里我们逆向推导,现有这样一个更新操作,要将某表中的一个字段state从1改为0

1、如果是先写入redo,再写入binlog:
如果刚写完redo,服务崩溃了,再次重启时需要做数据恢复
因为这里redo已经写入完成了,事务已经生效,所以我们数据恢复就要恢复成事务完成后的状态,即将state恢复为0;重启服务后,因为有redo记录,数据会更新成0,但是如果这时执行了binlog的数据恢复,因为binlog是没有这条操作记录的,针对state的上一次记录是1,则会恢复为1,与我们想要恢复的值不符,也就产生了问题

2、如果是先写入binlog,再写入redo:
如果刚写完binlog,服务崩溃了,同样重启后需要做数据恢复
因为redo中没有这条操作的记录,事务没有生效,所以数据恢复是要恢复成事务开始之前的状态,即将state恢复成1;重启服务后,因为没有redo记录,系统不做事务操作,但是有binlog中‘1变成0’的记录,这时进行数据恢复,会将数据更新为0(产生了一个新的事务),与我们想要恢复的值也不同

可以使用binlog替代redolog进行数据恢复吗?

不可以

innodb利用wal技术进行数据恢复,write ahead logging技术依赖于物理日志进行数据恢复,binlog不是物理日志是逻辑日志,因此无法使用;
那么,为什么write ahead logging技术不可以使用逻辑日志进行数据恢复呢?这个问题可以考虑一下自增锁的场景,当自增锁的模式设置为innodb_autoinc_lock_mode = 2时,mysql会锁住分配自增值的代码逻辑,不去进行自增值的预分配,由此带来的问题就是,高并发场景下多个事务中的insert(单条insert语句包含多个待插入值)逻辑会造成自增ID不固定的问题,由此带来的结果就是,利用binlog中的逻辑日志进行主从复制时,从库中的ID和主库中的ID不一致。因此,在特定场景下,逻辑日志相对于物理日志,显得不是那么可靠。

 可以只使用redolog而不使用binlog吗?

不可以

redolog是循环写,写到末尾要回到开头继续写,这样的日志无法保留历史记录,无法进行数据复制。
个人理解redolog其实是物理数据的一个缓存,理论上可以不需要redolog,插入的数据落盘后再返回插入成功,但是数据落盘的过程比较耗时,需要更新各种索引(B+树),因此现在数据落入redolog即返回成功,加快了返回速度。

为什么执行顺序是: redolog(prepare 准备状态)--->binlog--->redo log(commit 提交状态)?

假设执行顺序是 redolog(提交)- binlog

发生异常重启的状况,导致数据日志丢失

binlog日志丢失:对于一个数据库来说,当数据写入了(redolog记录到),但是没有写入记录(binlog没记录到)。相当于一个数据库只有数据,没有该数据的记录,一致性出错!
redolog日志丢失:对于一个数据库来说,当数据没有写入(redolog没记录到),但是却有记录(binlog记录到)。相当于对一个数据库来说,该数据有记录,但是查不到。
因此这也是为什么增删改语句的时候,执行顺序是:

redo log(prepare 状态)--->binlog--->redo log(commit状态)

这个时候发生了异常重启会怎么样呢? 这个就要依赖于 MySQL 的处理机制了,MySQL 的处理过程如下:

判断 redo log的状态,如果判断是是commit状态,就立即提交。
如果 redo log 只是预提交但不是 commit 状态,这个时候就会去判断 binlog 是否完整,如果完整就提交 redo log, 不完整就回滚事务。
结论:执行顺序很重要,这样执行的最终目的就是保持一致性!

有了redo log,为啥还需要binlog呢?

1、redo log 文件是固定大小的,是循环写的,写满了会从头继续写,而 binlog 是追加写的,写满了再新建文件接着写。
2、redo log是innodb引擎层实现的,并不是所有引擎都有。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Codigger数据篇(下):数据安全的全方位保障

在数字化浪潮中,数据已成为现代企业的核心财富。Codigger作为领先的数据服务平台,深知数据安全对于用户的重要性,因此在深挖数据价值的同时,我们始终坚守数据安全防线。 一、双重加密技术保障 Codigger平台运用先进的加密通信和…

vue2.7与vue2.6、vue3的区别

官网链接:https://v2.cn.vuejs.org/v2/guide/migration-vue-2-7.html -组合式与选项式 选项式:export default { 各种选项关键字名,都定好了,无需引入,配对放置即可}

stm32单片机开发一、中断之外部中断实验

stm32单片机的外部中断和定时器中断、ADC中断等都由stm32的内核中的NVIC模块控制,stm32的中断有很多中,比如供电不足中断,当供电不足时,会产生的一种中断,这么多中断如果都接在CPU上,或者说CPU去处理&#…

Leetcode—2639. 查询网格图中每一列的宽度【简单】

2024每日刷题&#xff08;121&#xff09; Leetcode—2639. 查询网格图中每一列的宽度 实现代码 class Solution { public:int func(int num) {if(num 0) {return 1;}int len 0;while(num ! 0) {len;num / 10;}return len;}vector<int> findColumnWidth(vector<ve…

如何测试响应式网站

我们每天通过多种设备访问互联网。移动电话&#xff0c;台式机/笔记本电脑&#xff0c;平板电脑&#xff0c;平板电脑…我们所掌握的设备数量已经增长为天文数字。作为消费者&#xff0c;体验很棒。我们可以随时随地在任何设备上自由访问互联网。但对于Web开发人员&#xff0c;…

类加载子系统之类的生命周期(待完善)

0、前言 文中大量图片来源于 B站 黑马程序员 0.1、类加载子系统在 JVM 中的位置 类加载器负责的事情是&#xff1a;加载、链接、解析 0.2、与类的生命周期相关的虚拟机参数 参数描述-XX:TraceClassLoading打印出加载且初始化的类 1、类的生命周期 堆上的变量在分配空间的时…

【C++STL详解(三)】------vector的介绍与使用

目录 前言 一、关于数组 二、vector的介绍 三、vector的使用 Ⅰ、默认成员函数 1.构造函数 2.赋值重载 3.析构函数 Ⅱ、容量 1.size(&#xff09; 2.capacity() 3.empty() 4.resize() 5.reserve() Ⅲ、遍历操作 1.迭代器 begin() end()&#xff08;正向迭代器…

element 分页切换时:current-page无效 页数不会跟着一起切换

问题回溯&#xff1a;使用el-pagination组件 选择切换当前分页 页数为2 问题结果&#xff1a;el-pagination组件 当前页切换失败 一直都是 1&#xff0c;接口传参分页数据是2&#xff0c;打印当前分页也是2 解决方案1&#xff1a;使用 current-page参数 .sync 修饰符 解决方案2…

rust将json字符串直接转为map对象或者hashmap对象

有些时候我们还真的不清楚返回的json数据里面到底有哪些数据&#xff0c;数据类型是什么等&#xff0c;这个时候就可以使用批处理的方式将json字符串转为一个对象&#xff0c;然后通过这个对象的get方法来获取json里面的数据。 pub async fn test_json(&self) {let json_st…

STM32的TIM输入捕获和PWMI详解

系列文章目录 STM32单片机系列专栏 C语言术语和结构总结专栏 文章目录 1. IC输入捕获 2. 频率测量 3. 主模式、从模式、触发源选择 4. 输入捕获基本结构 5. PWMI模式 6. 代码示例 6.1 PWM.c 6.2 PWM.h 6.3 IC.c 6.4 IC.h 6.5 完整工程文件 输出比较可以看下面这篇…

numpy+matplotlib绘制阿基米德螺线

【第10次课]实验十一数据可视化及应用】 声明&#xff1a;著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 绘制阿基米德螺线&#xff0c;运行效果如图所示。 参数方程为: x icosi yisini 其中半径i和圆心角i变化一致&#xff0c;取值范围为…

#你觉得未来的智慧工地是什么样子的#

#你觉得未来的智慧工地是什么样子的# 有人说“现阶段的智慧工地都是噱头&#xff0c;实际用处不大”&#xff1b;也有人将智慧工地吹嘘上天。那么&#xff0c;随着技术的发展&#xff0c;你觉得未来的智慧工地会是什么样子呢&#xff1f; 随着大数据时代的到来&#xff0c;未来…

Three.js杂记(十五)—— 汽车展览(下)

在上一篇文章Three.js杂记&#xff08;十四&#xff09;—— 汽车展览上 - 掘金 (juejin.cn)中主要对切换相机不同位置和鼠标拖拽移动相机焦点做了简单的应用。 那么现在聊聊该如何实现汽车模型自带的三种动画展示了&#xff0c;实际上可以是两种汽车前后盖打开和汽车4车门打开…

抑郁后的症状表现——XWX-QP大小鼠强迫游泳桶硬件

简单介绍&#xff1a; 大小鼠强迫游泳桶硬件主要用于抗抑郁的研究。适用于大鼠、小鼠或其他实验室动物&#xff0c;通过将实验动物置于一个局限的环境中&#xff0c;动物在该环境中拼命挣扎试图逃跑又无法逃脱&#xff0c;从而提供了一个无可回避的压迫环境&#xff0c;动物的…

如何提取二维码文本信息?文本二维码提取内容的方法

如何分解出二维码中的文本信息呢&#xff1f;很多商家在做活动时会给每个用户生成一个单独的二维码&#xff0c;每一个二维码中有单独的编号信息&#xff0c;那么当我们收集到用户的二维码时&#xff0c;如何操作才能够提取二维码中的编号信息呢&#xff1f;想要解决这个问题可…

双目深度估计原理立体视觉

双目深度估计原理&立体视觉 0. 写在前面1. 双目估计的大致步骤2. 理想双目系统的深度估计公式推导3. 双目标定公式推导4. 极线校正理论推导 0. 写在前面 双目深度估计是通过两个相机的对同一个点的视差来得到给该点的深度。 标准系统的双目深度估计的公式推导需要满足:1)两…

Vue3+ts(day04:watch、watchEffect)

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/frontlearningNotes 觉得有帮助的同学&#xff0c;可以点心心支持一下哈&#xff08;笔记是根据b站上学习的尚硅谷的前端视频【张天禹老师】&#xff0c;记录一下学习笔记&#xff0c;用于自己复盘&#xff0c;有需要学…

树莓派5用docker运行Ollama3

书接上回&#xff0c;树莓派5使用1panel安装 Ollama 点击终端就可以进入容器 输入以下代码 ollama run llama3Llama3 是市场推崇的版本。您的 树莓派5上必须至少有 4.7GB 的可用空间&#xff0c;因此用树莓派玩机器学习就必须配置大容量的固态硬盘。用1panel部署网络下载速度…

Python | Leetcode Python题解之第58题最后一个单词的长度

题目&#xff1a; 题解&#xff1a; class Solution:def lengthOfLastWord(self, s: str) -> int:ls[]for i in s.split():ls.append(i)return len(ls[-1])

跟TED演讲学英文:The future will be shaped by optimists by Kevin Kelly

The future will be shaped by optimists Link: https://www.ted.com/talks/kevin_kelly_the_future_will_be_shaped_by_optimists Speaker: Kevin Kelly Date: August 2021 文章目录 The future will be shaped by optimistsIntroductionVocabularyTranscriptSummary后记 In…