初步了解InnoDB存储引擎的架构设计

1. 更新语句在MySQL中是如何执行的?

之前我们已经分析了MySQL架构上的整体设计原理,现在对一条SQL语句从我们的系统层面发送到MySQL中,然后一步一步执行这条SQL的流程,都有了一个整体的了解。

我们已经知道了,MVSQL最常用的就是InnoDB存储引擎,那么我们今天借助一条更新语句的执行,来初步的了解-下InnoDB存储引擎的架构设计。

首先假设我们有一条SQL语句是这样的:

update users set name='xxx'where id=10

那么我们先想一下这条SQL语句是如何执行的?

首先肯定是我们的系统通过一个数据库连接发送到了MVSQL上,然后肯定会经过SQL接口、解析器、优化器、执行器几个环节,解析SQL语句,生成执行计划,接着去由执行器负责这个计划的执行,调用InnoDB存储引擎的接口去执行。

所以先看下图,大致还是会走下图的这个流程

今天我们就来探索一下这个存储引擎里的架构设计,以及如何基于存储引擎完成一条更新语句的执行

2. InnoDB的重要内存结构:缓冲池

InnoDB存储引擎中有一个非常重要的放在内存里的组件,就是缓冲池(Buffer Pool),这里面会缓存很多的数据,以便于以后在查询的时候,万一你要是内存缓冲池里有数据,就可以不用去查磁盘了,我们看下图。

InnoDB存储引擎要执行更新语句的时候,比如对“id=10”这一行数据,他其实会先将“id=10”这一行数据看看是否在缓冲池里,如果不在的话,那么会直接从磁盘里加载到缓冲池里来,而且接着还会对这行记录加独占锁。因为我们想一下,在我们更新“id=10”这一行数据的时候,肯定是不允许别人同时更新的,所以必须要对这行记录加独占锁

至于锁的详细分析,我们后续也会有,大家不用着急,在这里先初步了解即可,我们看下面的图

3. undo日志文件:如何让你更新的数据可以回滚?

接着下一步,假设“id=10”这行数据的name原来是“zhangsan”,现在我们要更新为“xxx”,那么此时我们得先把要更新的原来的值“zhangsan”和“id=10”这些信息,写入到undo日志文件中去。

其实稍微对数据库有一点了解的同学都应该知道,如果我们执行一个更新语句,要是他是在一个事务里的话,那么事务提交之前我们都是可以对数据进行回滚的,也就是把你更新为“xxx”的值回滚到之前的“zhangsan”去。

所以为了考虑到未来可能要回滚数据的需要,这里会把你更新前的值写入undo日志文件,我们看下图。

4. 更新buffer pool中的缓存数据

当我们把要更新的那行记录从磁盘文件加载到缓冲池,同时对他加锁之后,而且还把更新前的旧值写入undo日志文件之后,我们就可以正式开始更新这行记录了,更新的时候,先是会更新缓冲池中的记录,此时这个数据就是脏数据了。

这里所谓的更新内存缓冲池里的数据,意思就是把内存里的“id=10”这行数据的name字段修改为“xxx”

那么为什么说此时这行数据就是脏数据了呢?

因为这个时候磁盘上“id=10”这行数据的name字段还是“zhanqsan”,但是内存里这行数据已经被修改了,所以就会叫他是脏数据。

我们看下图,我同时把几个步骤的序号标记出来了,

5. Redo Log Buffer:万一系统宕机,如何避免数据丢失?

接着我们来思考一个问题,按照上图的说明,现在已经把内存里的数据进行了修改,但是磁盘上的数据还没修改那么此时万-MVSQL所在的机器宕机了,必然会导致内存里修改过的数据丢失,这可怎么办呢?

这个时候,就必须要把对内存所做的修改写入到一个Redo Loq Buffer里去,这也是内存里的一个缓冲区,是用来存放redo日志的

所谓的redo日志,就是记录下来你对数据做了什么修改,比如对“id=10这行记录修改了name字段的值为xxx”这就是一个日志。

我们先看下图的示意

这个redo日志其实是用来在MySQL突然宕机的时候,用来恢复你更新过的数据的,但是我们现在还没法直接讲解redo是如何使用的,毕竟现在redo日志还仅仅停留在内存缓冲里

大家稍安勿躁,继续往下看

6. 如果还没提交事务,MySQL宕机了怎么办?

这里我们假设每个人看专栏的人,都对MVSQL的基本SQL语法、事务的基本概念以及索引的基本概念有一个基础的了解,因为但凡一个后端工程师,要跟数据库打交道,必然会跟这些概念有一定的了解。

所以我们都知道,其实在数据库中,哪怕执行一条SQL语句,其实也可以是一个独立的事务,只有当你提交事务之后,SQL语句才算执行结束,

所以这里我们都知道,到目前为止,其实还没有提交事务,那么此时如果MVSQL崩溃,必然导致内存里BufferPool中的修改过的数据都丢失,同时你写入Redo Log Buffer中的redo日志也会丢失

我们看下图

那么此时数据丢失要紧吗?

其实是不要紧的,因为你一条更新语句,没提交事务,就代表他没执行成功,此时MSQL宕机虽然导致内存里的数据都丢失了,但是你会发现,磁盘上的数据依然还停留在原样子,

也就是说,“id=1”的那行数据的name字段的值还是老的值,“zhangsan”,所以此时你的这个事务就是执行失败了,没能成功完成更新,你会收到一个数据库的异常。然后当mysql重启之后,你会发现你的数据并没有任何

变化。

所以此时如果mysql宕机,不会有任何的问题。

7. 提交事务的时候将redo日志写入磁盘中

接着我们想要提交一个事务了,此时就会根据一定的策略把redo日志从redolog buffer里刷入到磁盘文件里去

此时这个策略是通过innodb flush log at trx commit来配置的,他有几个选项。

当这个参数的值为0的时候,那么你提交事务的时候,不会把redolog buffer里的数据刷入磁盘文件的,此时可能你都提交事务了,结果mysql宕机了,然后此时内存里的数据全部丢失。

相当于你提交事务成功了,但是由于MySQL突然宕机,导致内存中的数据和redo日志都丢失了,我们看下图:

当这个参数的值为1的时候,你提交事务的时候,就必须把redo log从内存刷入到磁盘文件里去,只要事务提交成功,那么redoloq就必然在磁盘里了,我们看下图:

那么只要提交事务成功之后,redo日志一定在磁盘文件里,此时你肯定会有一条redo日志说了,“我此时对哪个数据做了一个什么修改,比如name字段修改为xxx了”

然后哪怕此时buffer pool中更新过的数据还没刷新到磁盘里去,此时内存里的数据是已经更新过的“name=xxx”,然后磁盘上的数据还是没更新过的“name=zhangsan”

我们看下图,提交事务之后,可能处于的一个状态。

此时如果说提交事务后处于上图的状态,然后mysql系统突然崩溃了,此时会如何?会丢失数据吗?

肯定不会啊,因为虽然内存里的修改成name=xxx的数据会丢失,但是redo日志里已经说了,对某某数据做了修改name=XXX

所以此时mysql重启之后,他可以根据redo日志去恢复之前做过的修改,我们看下图。

最后来看看,如果innodb_flush_log_at trx_commit参数的值是2呢?

他的意思就是,提交事务的时候,把redo日志写入磁盘文件对应的os cache缓存里去,而不是直接进入磁盘文件,可能1秒后才会把os cache里的数据写入到磁盘文件里去。

这种模式下,你提交事务之后,redolog可能仅仅停留在os cache内存缓存里,没实际进入磁盘文件,万一此时你要是机器宕机了,那么os cache里的redo log就会丢失,同样会让你感觉提交事务了,结果数据丢了,看下图。

8. 小思考题:三种redo日志刷盘策略到底选择哪一种?

今天给大家留一个小的思考题,大家觉得在提交事务的时候,我们对redo日志的刷盘策略应该选择哪一种?每一种刷盘策略的优缺点分别是什么?为什么?

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

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

相关文章

Springboot 初始化操作

在使用Springboot过程中,或多或少我们会遇到在Springboot启动时要初始化类,或者加载文件之类的一些操作。关于初始化,主要分为两类,一类是在程序启动后的执行初始化操作,另一类是Bean实例化时执行初始化操作&#xff0…

3D Tiles 规范(一概述)

3D Tiles 专为流式传输和渲染大量 3D 地理空间内容而设计,例如摄影测量、3D 建筑、BIM/CAD、实例化要素和点云。它定义了分层数据结构和一组提供可渲染内容的Tile格式。3D Tiles 没有定义内容可视化的明确规则;客户可以根据自己认为合适的方式可视化 3D …

如何理解Vue 3组件的component关键字

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Verilog仿真跨模块调用内部信号的方法

在Verilog仿真时如果需要调用某子模块中的信号在本模块中使用可以使用层次化引用的方法,而不需要在rtl部分用端口引出来。 引用方式:当前例化模块名.子例化模块名.子子例化模块名.参数 将需要的信号引出。 注意是用例化模块名而不是用子模块名&#xff…

【C++】二维数组传参方式

最近刚开始刷剑指offer,刚做到第三题的时候,发现C二维数组的传参方式和C语言略有些不同,所以在这篇博客中,会列出C/C常见的二维数组传参方式。(本方式和代码都是基于vs环境所编写) 一.C语言二维数组传参方式…

CCF区块链论文录用资讯--ICSE 2024

ICSE是CCF A类会议 (软件工程/系统软件/程序设计语言) 其2024录用了13篇区块链论文 Smart Contract and DeFi Security Tools: Do They Meet the Needs of Practitioners? 智能合约和 DeFi 安全工具:它们满足从业者的需求吗? St…

SegAnyGAussians(SAGA)项目配置和运行

GitHub项目地址:Jumpat/SegAnyGAussians: The official implementation of SAGA (Segment Any 3D GAussians) (github.com) 一、项目准备 1、下载原项目的zip包解压 2、下载third_party目录下的两个模块,放到对应目录下 3、下载预训练模型和数据集 数据…

非计算机专业,如何从事研发岗位的建议!

首先,非计算机专业的毕业生通过读研和专门的培训是完全可以进入IT行业的,目前IT行业内也有大量非计算机专业毕业的技术开发(研发)人员,其中有不少人也非常优秀,发展空间同样比较大。 虽然IT行业内整体的人才…

IPFS分布式存储系统

一、 引言 IPFS是InterPlanetary File System的缩写。它是一个分布式的网络传输协议,它可以把文件分成很多小块放到服务器的不同地方,然后用一种特别的方式来寻找和传输这些小块。这样,我们就可以更快、更安全、更抗容错了的存储文件了。 可能…

从小到大输出四个整数(C语言)

一、N-S流程图&#xff1b; 二、运行结果&#xff1b; 三、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int a, b, c, d;int t 0;//提示用户&#xff1b;printf("请输入四个整数a b c d&…

python怎么判断整数

isinstance()函数 可以用来判断变量的类型&#xff0c;它返回的是一个布尔值&#xff0c;False or True。 >>>isinstance("123",str) >>>Flase >>>isinstance(123,int) >>>True >>>isinstance({123},list) >>&g…

【大数据】分布式文件系统HDFS

目录 1.什么是分布式文件系统 2.HDFS的特点 3.HDFS的核心概念 4.HDFS的体系结构 5.HDFS的配置建议 6.HDFS的局限性 7.HDFS的存储机制 7.1.数据冗余机制 7.2.错误与恢复 8.HDFS数据读写过程 1.什么是分布式文件系统 分布式文件系统是整个大数据技术的基础&#xff0c…

京东AI数字人“采销东哥”首秀观看量破2000万;天工 SkyMusic 音乐大模型开放公测

&#x1f989; AI新闻 &#x1f680; 京东AI数字人“采销东哥”首秀观看量破2000万 摘要&#xff1a;京东AI数字人“采销东哥”由京东云言犀打造&#xff0c;在其直播首秀中亮相并迅速吸引超2000万观看量。尽管“采销东哥”的外形和口音与创始人刘强东相似&#xff0c;但其直…

C语言的OJ判题机设计与实现

1. 接收判题入参 判题需要作答代码、测试输入和期望输出、编译器名称、时空限制。对于支持special judge的还需要传入是否为sj和sj代码。推荐使用消息队列&#xff0c;应对高并发的比赛情况会比较好。 但是消息队列是异步的&#xff0c;我为了快点实现能提交后在当前页面获得判…

量子密钥分发系统的设计与实现(二):光路子系统初步讨论

通过上一篇文章&#xff0c;我们对量子密钥分发系统的基本架构、硬件结构以及密钥分发流程进行了初步的总体介绍&#xff0c;从本文开始&#xff0c;我们就基于系统顶层的架构设计&#xff0c;开始从模块到器件&#xff0c;从硬件到软件开始详细讨论QKD系统的设计与实现。本文主…

双向链表详解

目录 带头双向循环链表带头双向循环链表的实现带头双向循环链表的功能实现创造新节点LTNode* CreateLTNode(LTDataType x)代码 初始化链表LTNode*LTInit(LTNode* phead)代码 打印链表void LTPrint(LTNode* phead)代码 链表尾插void LTPushBack(LTNode* phead, LTDataType x)代码…

C#语法知识之运算符

3、运算符 1、算数运算符 1、赋值符号 //把右侧的值赋给左侧的变量2、算数运算符 _ * / float f 1 / 2f; %3、算数运算符的优先级 //乘除余优先级高于加减 括号可以改变优先级&#xff0c;优先计算括号内的内容4、算数运算符的复合运算 复合运算符是用于自己 自己进行运算…

源码解读——SplitFed: When Federated Learning Meets Split Learning

源码地址 1. 源码概述 源码里一共包含了5个py文件 单机模型&#xff08;Normal_ResNet_HAM10000.py&#xff09;联邦模型&#xff08;FL_ResNet_HAM10000.py&#xff09;本地模拟的SFLV1&#xff08;SFLV1_ResNet_HAM10000.py&#xff09;网络socket下的SFLV2&#xff08;SF…

51单片机入门_江协科技_33~34_OB记录的自学笔记_LED呼吸灯与PWM直流马达调速

33. 直流电机驱动(PWM) 33.1. 直流电机介绍 •直流电机是一种将电能转换为机械能的装置。一般的直流电机有两个电极&#xff0c;当电极正接时&#xff0c;电机正转&#xff0c;当电极反接时&#xff0c;电机反转 •直流电机主要由永磁体&#xff08;定子&#xff09;、线圈&…

MySQL 死锁案例解析一则

原文链接&#xff1a;https://www.modb.pro/db/448666 一、问题背景某业务模块反馈数据库最近出现过几次死锁告警的情况&#xff0c;本文总结了这次死锁排查的全过程&#xff0c;并分析了导致死锁的原因及解决方案。希望给大家提供一个死锁的排查及解决思路。基础环境&#xff…