当前位置: 首页 > article >正文

MySQL--》深度解析InnoDB引擎的存储与事务机制

目录

InnoDB架构

事务原理

MVCC


InnoDB架构

从MySQL5.5版本开始默认使用InnoDB存储引擎,它擅长进行事务处理,具有崩溃恢复的特性,在日常开发中使用非常广泛,其逻辑存储结构图如下所示,

下面是InnoDB架构图,左侧为内存结构,右 侧为磁盘结构,如下所示:

内存结构:主要有以下几部分组成,其特点如下所示:

1)Buffer Pool:缓冲池是主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行增删改查操作时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),然后再以一定频率刷新到磁盘,从而减少磁盘I0,加快处理速度。

缓冲池:以Page页为单位,底层采用链表数据结构管理Page,根据状态可以将Page分为三种类型:

free page:空闲page,未被使用。·

cleanpage:被使用page,数据没有被修改过。·

dirtypage:脏页,被使用page,数据被修改过,也中数据与磁盘的数据产生了不一致。

2)ChangeBuffer:更改缓冲区(针对于非唯一二级索引页),在执行DML语句时,如果这些数据Page没有在BufferPool中,不会直接操作磁盘,而会将数据变更存在更改缓冲区ChangeBuffer中,在未来数据被读取时,再将数据合并恢复到BufferPool中,再将合并后的数据刷新到磁盘中。与聚集索引不同,二级索引通常是非唯一的,并且以相对随机的顺序插入二级索引。同样,删除和更新可能会影响索引树中不相邻的二级索引页,如果每一次都操作磁盘,会造成大量的磁盘IO。有了ChangeBuffer之后,我们可以在缓冲池中进行合并处理,减少磁盘lO。

3)AdaptiveHashIndex:自适应hash索引,用于优化对BufferPool数据的查询。InnoDB存储引擎会监控对表上各索引页的查询,如果观察到hash索引可以提升速度,则建立hash索引l,称之为自适应hash索引。自适应哈希索引,无需人工干预,是系统根据情况自动完成。参数:adaptive_hash_index

4)LogBuffer:日志缓冲区,用来保存要写入到磁盘中的log日志数据(redolog、undolog),默认大小为16MB,日志缓冲区的日志会定期刷新到磁盘中。如果需要更新、插入或删除许多行的事务,增加日志缓冲区的大小可以节省磁盘1/0。

参数:innodb_log_buffer_size:缓冲区大小

innodb_flush_log_at_trx_commit:日志刷新到磁盘时机

磁盘结构:主要有以下几部分组成,其特点如下所示:

1)SystemTablespace:系统表空间是更改缓冲区的存储区域。如果表是在系统表空间而不是每个表文件或通用表空间中创建的,它也可能包含表和索引数据。(在MySQL5.x版本中还包含lnnoDB数据字典、undolog等)参数:innodb_data_file_path

2)File-Per-TableTablespaces:每个表的文件表空间包含单个lnnoDB表的数据和索引,并存储在文件系统上的单个数据文件中。参数:innodb_file_per_table

3)GeneralTablespaces:通用表空间,需要通过CREATETABLESPACE语法创建通用表空间,在创建表时,可以指定该表空间。

4)UndoTablespaces:撤销表空间,MySQL实例在初始化时会自动创建两个默认的undo表空间(初始大小16M),用于存储undolog日志。

5)Temporary Tablespaces:InnoDB使用会话临时表空间和全局临时表空间。存储用户创建的临时表等数据。

6)DoublewriteBufferFiles:双写缓冲区,innoDB引擎将数据页从BufferPool刷新到磁盘前,先将数据页写入双写缓冲区文件中,便于系统异常时恢复数据。

7)RedoLog:重做日志,是用来实现事务的持久性。该日志文件由两部分组成:重做日志缓冲(redologbuffer)以及重做日志文件(redolog),前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都会存到该日志中,用于在刷新脏页到磁盘时,发生错误时,进行数据恢复使用。

后台线程:InnoDB存储引擎缓冲池中主要有四个后台线程,它们主要内容如下:

1)Master Thread:核心后台线程,负责调度其他线程,还负责将缓冲池中的数据异步刷新到磁盘中,保持数据的一致性,还包括脏页的刷新、合并插入缓存、undo页的回收。

2)I0 Thread:在lnnoDB存储引擎中大量使用了AIO来处理IO请求,这样可以极大地提高数据库的性能,而IOThread主要负责这些lO请求的回调,线程类型如下所示:

线程类型默认个数职责
Read thread4负责读操作
Write thread4负责写操作
Log thread1负责将日志缓冲区刷新到磁盘
Insert buffer thread1负责将写缓冲区内容刷新到磁盘

3)Purge Thread:主要用于回收事务已经提交了的undolog,在事务提交之后,undolog可能不用了,就用它来回收。

4)Page Cleaner Thread:协助MasterThread刷新脏页到磁盘的线程,它可以减轻Master Thread的工作压力,减少阻塞。

事务原理

事务:事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败,其特性如下所示:

1)原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。

2)一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。

3)隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。

4)持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。

这些特性涉及的原理主要分为以下两者情况:

1)redo log:重做日志,记录的是事务提交时数据页的物理修改是用来实现事务的持久性,该日志文件由两部分组成:重做日志缓冲(redologbuffer)以及重做日志文件(redologfile),前者是在内存中,后者在磁盘中。

当事务提交之后会把所有修改信息都存到该日志文件中,用于在刷新脏页到磁盘,发生错误时,进行数据恢复使用,如下所示:

2)undo log:回滚日志,用于记录数据被修改前的信息,作用包含两个:提供回滚和 MVCC(多版本并发控制)。

undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。

当执行rollback时,就可以从undolog中的逻辑记录读取到相应的内容并进行回滚,如下所示:

undo log销毁:undo log在事务执行时产生,事务提交时,并不会立即删除undo log,因为这些日志可能还用于MVCC。

undo log存储:undo log采用段的方式进行管理和记录,存放在前面介绍的rollback segment回滚段中,内部包含1024个undo log segment。

MVCC

MVCC:通过在数据库中保存多个数据版本,允许读操作不加锁,同时写操作不会阻塞读取从而提高并发性能,MVCC依赖于事务的快照隔离(Snapshot Isolation)级别,确保每个事务看到的是一致的视图,对于读取数据主要分为以下两种:

1)当前读:读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁,对于我们日常的操作,如:select...lock in share mode(共享锁),select...for update、update、insert、delete(排他锁)都是一种当前读。

2)快照读:简单的select(不加锁)就是快照读,快照读读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。

Read Committed:每次select都生成一个快照读。

Repeatable Read:开启事务后第一个select语句才是快照读的地方。

Serializable:快照读会退化为当前读。

其实现原理如下图所示:

MVCC使得读写操作没有冲突,快照读为MySQL实现MVCc提供了一个非阻塞读功能,MVCC的具体实现还需要依赖于数据库记录中的三个隐式字段、undo log日志、readView,如下:

隐式字段:当我们创建一张表的时候,默认记录中会有三个隐藏的字段,如下所示:

隐藏字段含义
DB_TRX_ID最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID。
DB_ROLL_PTR回滚指针,指向这条记录的上一个版本,用于配合undolog,指向上一个版本。
DB_ROW_ID隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。

undo log日志:回滚日志,在insert、update、delete的时候产生的便于数据回滚的日志:

当insert的时候,产生的undolog日志只在回滚时需要,在事务提交后,可被立即删除

当update、delete的时候,产生的undolog日志不仅在回滚时需要,在快照读时也需要,不会立即被删除。

不同事务或相同事务对同一条记录进行修改,会导致该记录的undo log生成一条记录版本链表,链表的头部是最新的旧记录,链表尾部是最早的旧记录,如下所示:

readView:readView(读视图)是快照读SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务(未提交的)id,readView中包含了四个核心字段如下所示:

字段含义
m_ids当前活跃的事务ID集合
min_trx_id最小活跃事务ID
max_trx_id预分配事务ID,当前最大事务ID+1(因为事务ID是自增的)
creator_trx_idReadView创建者的事务ID

版本链数据的访问规则如下所示:

不同的隔离级别,生成的readView的时机不同,如下所示:

1)read committed:在事务中每一次执行快照读时生成的readView,如下所示:

比如当前我们访问这条记录的事务id小于我们的最小活动事务的id,那么就说明当前的这条记录已经提交了,此时就说明这一次快照读就是我们当前访问的这条记录,如下是DB_TRX_ID为2就是我们要访问的记录:

2)repeatable read:仅在事务第一次执行快照读时生成readView,后续复用该readView

相关文章:

MySQL--》深度解析InnoDB引擎的存储与事务机制

目录 InnoDB架构 事务原理 MVCC InnoDB架构 从MySQL5.5版本开始默认使用InnoDB存储引擎,它擅长进行事务处理,具有崩溃恢复的特性,在日常开发中使用非常广泛,其逻辑存储结构图如下所示, 下面是InnoDB架构图&#xf…...

SpringCloudAlibaba 服务保护 Sentinel 项目集成实践

目录 一、简介1.1、服务保护的基本概念1.1.1、服务限流/熔断1.1.2、服务降级1.1.3、服务的雪崩效应1.1.4、服务的隔离的机制 1.2、Sentinel的主要特性1.3、Sentinel整体架构1.4、Sentinel 与 Hystrix 对比 二、Sentinel控制台部署3.1、版本选择和适配3.2、本文使用各组件版本3.…...

c++面试:类定义为什么可以放到头文件中

这个问题是刚了解预编译的时候产生的疑惑。 声明是指向编译器告知某个变量、函数或类的存在及其类型,但并不分配实际的存储空间。声明的主要目的是让编译器知道如何解析程序中的符号引用。定义不仅告诉编译器实体的存在,还会为该实体分配存储空间&#…...

DeepSeek理解概率的能力

问题: 下一个问题是概率问题。乘车时有一个人带刀子的概率是百分之一,两个人同时带刀子的概率是万分之一。有人认为如果他乘车时带上刀子,那么还有其他人带刀子的概率就是万分之一,他乘车就会安全得多。他的想法对吗?…...

STM32 GPIO配置 点亮LED灯

本次是基于STM32F407ZET6做一个GPIO配置,实现点灯实验。 新建文件 LED.c、LED.h文件,将其封装到Driver文件中。 双击Driver文件将LED.c添加进来 编写头文件,这里注意需要将Driver头文件声明一下。 在LED.c、main.c里面引入头文件LED.h LED初…...

模板泛化类如何卸载释放内存

CustomWidget::~CustomWidget() {for (size_t i 0; i < buttonManager.registerItem.size(); i) {delete buttonManager.registerItem(exitButton);} } 以上该怎么写删除对象操作&#xff0c;类如下&#xff1a;template <typename T> class GenericManager { public…...

MFC结构体数据文件读写实例

程序功能将结构体内数组数据写入文件和读出 2Dlg.h中代码: typedef struct Student {int nNum[1000];float fScore;CString sss;}stu; class CMy2Dlg : public CDialog { // Construction public:CMy2Dlg(CWnd* pParent NULL); // standard constructorstu stu1; ... } 2Dl…...

jemalloc 5.3.0的tsd模块的源码分析

一、背景 在主流的内存库里&#xff0c;jemalloc作为android 5.0-android 10.0的默认分配器肯定占用了非常重要的一席之地。jemalloc的低版本和高版本之间的差异特别大&#xff0c;低版本的诸多网上整理的总结&#xff0c;无论是在概念上和还是在结构体命名上在新版本中很多都…...

03-机器学习-数据获取

一、流行机器学习数据集 主流机器学习数据集汇总 数据集名称描述来源MNIST手写数字图像数据集&#xff0c;由美国人口普查局员工书写。MNIST官网ImageNet包含数百万张图像&#xff0c;用于图像分类和目标检测。ImageNet官网AudioSet包含YouTube音频片段&#xff0c;用于声音分…...

编程题-最长的回文子串(中等)

题目&#xff1a; 给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。 示例 1&#xff1a; 输入&#xff1a;s "babad" 输出&#xff1a;"bab" 解释&#xff1a;"aba" 同样是符合题意的答案。示例 2&#xff1a; 输入&#xff1a;s &…...

爱书爱考平台说明

最近我开发了一个综合性的考试平台&#xff0c;内容包括但不限于职业资格证考试、成人教育、国家公务员考试等内容。目前1.0版本已经开发完成&#xff0c;其他的功能陆续完善中。 微信小程序搜索"爱书爱考" 微信小程序图标如下图: 目前维护了java相关的面试题的考题…...

doris: MAP数据类型

MAP<K, V> 表示由K, V类型元素组成的 map&#xff0c;不能作为 key 列使用。 目前支持在 Duplicate&#xff0c;Unique 模型的表中使用。 K, V 支持的类型有&#xff1a; BOOLEAN, TINYINT, SMALLINT, INT, BIGINT, LARGEINT, FLOAT, DOUBLE, DECIMAL, DECIMALV3, DAT…...

JUC--ConcurrentHashMap底层原理

ConcurrentHashMap底层原理 ConcurrentHashMapJDK1.7底层结构线程安全底层具体实现 JDK1.8底层结构线程安全底层具体实现 总结JDK 1.7 和 JDK 1.8实现有什么不同&#xff1f;ConcurrentHashMap 中的 CAS 应用 ConcurrentHashMap ConcurrentHashMap 是一种线程安全的高效Map集合…...

Sklearn 中的逻辑回归

逻辑回归的数学模型 基本模型 逻辑回归主要用于处理二分类问题。二分类问题对于模型的输出包含 0 和 1&#xff0c;是一个不连续的值。分类问题的结果一般不能由线性函数求出。这里就需要一个特别的函数来求解&#xff0c;这里引入一个新的函数 Sigmoid 函数&#xff0c;也成…...

Spring Boot 自定义属性

Spring Boot 自定义属性 在 Spring Boot 应用程序中&#xff0c;application.yml 是一个常用的配置文件格式。它允许我们以层次化的方式组织配置信息&#xff0c;并且比传统的 .properties 文件更加直观。 本文将介绍如何在 Spring Boot 中读取和使用 application.yml 中的配…...

1.2第1章DC/DC变换器的动态建模-1.2Buck-Boost 变换器的交流模型--电力电子系统建模及控制 (徐德鸿)--读书笔记

1.2 Buck-Boost 变换器的交流模型 Buck- Boost变换器是一种典型的DC/DC变换器&#xff0c;具有升压和降压功能其输出电压的极性与输入电压相反&#xff0c;见图1-4a。当电感L的电流i(t)连续时一个开关周期可以分为两个阶段。在阶段1&#xff0c;开关在位置1时&#xff0c;即&am…...

数据结构:二叉树—面试题(一)

目录 1、相同的树 2、另一棵树的子树 3、翻转二叉树 4、平衡二叉树 5、对称二叉树 6、二叉树遍历 7、二叉树的分层遍历 1、相同的树 习题链接https://leetcode.cn/problems/same-tree/description/ 描述&#xff1a; 给你两棵二叉树的根节点 p 和 q &#xff0c;编写一…...

DDD 和 TDD

领域驱动设计&#xff08;DDD&#xff09; DDD 是一种软件开发方法&#xff0c;强调通过与领域专家的密切合作来构建一个反映业务逻辑的模型。其核心思想是将业务逻辑和技术实现紧密结合&#xff0c;以便更好地解决复杂的业务问题。 DDD 的关键概念&#xff1a; 1. 领域模型 …...

LangChain概述

文章目录 为什么需要LangChainLLM应用开发的最后1公里LangChain的2个关键词LangChain的3个场景LangChain的6大模块 为什么需要LangChain 首先想象一个开发者在构建一个LLM应用时的常见场景。当你开始构建一个新项目时&#xff0c;你可能会遇到许多API接口、数据格式和工具。对于…...

Java基于SSM框架的互助学习平台小程序【附源码、文档】

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…...

lightweight-charts-python 包 更新 lightweight-charts.js 的方法

lightweight-charts-python 是 lightweight-charts.js 的 python 包装&#xff0c;非常好用 lightweight-charts 更新比较频繁&#xff0c;导致 lightweight-charts-python 内置的 lightweight-charts 经常不是最新的。 新的 lightweight-charts 通常可以获得性能改进和bug修复…...

React第二十七章(Suspense)

Suspense Suspense 是一种异步渲染机制&#xff0c;其核心理念是在组件加载或数据获取过程中&#xff0c;先展示一个占位符&#xff08;loading state&#xff09;&#xff0c;从而实现更自然流畅的用户界面更新体验。 应用场景 异步组件加载&#xff1a;通过代码分包实现组件…...

C# Dynamic关键字

一、引言&#xff1a;开启动态编程之门 在 C# 的编程世界里&#xff0c;长久以来我们习惯了静态类型语言带来的严谨与稳定。在传统的 C# 编程中&#xff0c;变量的类型在编译时就已经确定&#xff0c;这就像是给每个变量贴上了一个固定的标签&#xff0c;在整个代码执行过程中…...

大一计算机的自学总结:位运算的应用及位图

前言 不仅异或运算有很多骚操作&#xff0c;位运算本身也有很多骚操作。&#xff08;尤其后几个题&#xff0c;太逆天了&#xff09; 一、2 的幂 class Solution { public:bool isPowerOfTwo(int n) {return n>0&&n(n&-n);} }; 根据二进制表示数的原理&#…...

解决报错“The layer xxx has never been called and thus has no defined input shape”

解决报错“The layer xxx has never been called and thus has no defined input shape”(这里写自定义目录标题) 报错显示 最近在跑yolo的代码时遇到这样一个错误&#xff0c;显示“the layer {self.name} has never been called”.这个程序闲置了很久&#xff0c;每次一遇到…...

【AI论文】FilmAgent: 一个用于虚拟3D空间中端到端电影制作自动化的多智能体框架

摘要&#xff1a;虚拟电影制作涉及复杂的决策过程&#xff0c;包括剧本编写、虚拟摄影以及演员的精确定位和动作设计。受近期基于语言智能体社会的自动化决策领域进展的启发&#xff0c;本文提出了FilmAgent&#xff0c;这是一个新颖的、基于大型语言模型&#xff08;LLM&#…...

hive:数据导入,数据导出,加载数据到Hive,复制表结构

hive不建议用insert,因为Hive是建立在Hadoop之上的数据仓库工具&#xff0c;主要用于批处理和大数据分析&#xff0c;而不是为OLTP&#xff08;在线事务处理&#xff09;操作设计的。INSERT操作会非常慢 数据导入 命令行界面:建一个文件 查询数据>>复制>>粘贴到新…...

VUE之路由Props、replace、编程式路由导航、重定向

目录 1、路由_props的配置 2、路由_replaces属性 3、编程式路由导航 4、路由重定向 1、路由_props的配置 1&#xff09;第一种写法&#xff0c;将路由收到的所有params参数作为props传给路由组件 只能适用于params参数 // 创建一个路由器&#xff0c;并暴露出去// 第一步…...

虹科分享 | 汽车NVH小课堂之听音辨故障

随着车主开始关注汽车抖动异响问题&#xff0c;如何根据故障现象快速诊断异响来源&#xff0c;成了汽修人的必修课。 一个比较常用的方法就是靠“听”——“听音辨故障”。那今天&#xff0c;虹科Pico也整理了几个不同类型的异响声音&#xff0c;一起来听听看你能答对几个吧 汽…...

Transfoemr的解码器(Decoder)与分词技术

在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;解码器&#xff08;Decoder&#xff09;和分词技术是两个至关重要的概念。解码器是序列生成任务的核心组件&#xff0c;而分词则是将文本数据转换为可处理形式的基础步骤。 一、解码器&#xff08;Decoder&…...