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

MySQL进阶篇-InnoDB引擎(超细)

文章目录

  • 前言
  • 逻辑存储结构
    • 研究B+树结构在InnoDB中到底是怎么存储的
  • 架构
    • 内存结构
      • BufferPool缓冲池
        • 正常查询缓冲池数据如何查询
      • Change Buffer更改缓冲区
        • why需要Change Buffer?
      • Adaptive Hash Index 自适应哈希索引
        • AHI和Buffer Pool之间一些联系
      • log Buffer
    • 磁盘结构
      • 为什么在内存的数据还需要存在磁盘中
    • 后台线程
  • 事务原理
    • redo log
  • MVCC
    • 基本概念
    • 隐藏字段
    • undo log版本链
    • read view介绍
      • RC级别,读分析
      • RR级别,读分析

前言

本篇文章主要介绍InnoDB存储引擎,会从四个方面来详解InnoDB,分别是逻辑存储结构、架构、事务原理、MVCC四个方面来剖析InnoDB

逻辑存储结构

在这里插入图片描述

  • 表空间(ibd文件) ,一个mysql实例可以对应多个表空间,用于存储记录、索引等数据。
  • ,分为数据段(Leaf node segment)、索引段 (Non-leaf node segment)、回滚段( Rollback segment) , InnoDB是索引组织表,数据段就是B+树的叶子节点,索引段即为B+树的非叶子节 点。段用来管理多个Extent (区)。
  • ,表空间的单元结构,每个区的大小为1M。默认情况下,InnoDB存储引擎页大小为16K,即一个区中这共有64个连续的页。
  • ,是InnoDB存储引擎磁盘管理的最小单元,每个页的大小默认为16KB。为了保证页的连续性, InnoDB 存储引擎每次从磁盘申请4-5个区。
  • ,InnoDB存储引擎数据是按行进行存放的。
    在这里插入图片描述

推荐学习这个视频!
8分钟精通MySql存储结构

研究B+树结构在InnoDB中到底是怎么存储的

首先我们要知道在InnoDB中所有数据都是以B+树形式构建的,所有数据行都在主键的叶子节点中
不按照B+树这种来进行存储,而按照表-叶子节点或者非叶子节点这种方式区别存储,所以说一个B+树中的叶子节点和和非叶子节点可能不属于一个区
!!!一个节点是一页!!!这个是福鼎的
表空间
一个表对应一个表空间.ibd文件(mysql8后)

分为非叶子节点段(索引段)和叶子结点段(数据段)
非叶子节点段只存储索引信息,叶子结点段可能存储数据行也可能存储当前值+对应主键
段(Segment)是独立分配区(Extent)的单位
比如叶子结点段申请区A、B、C,非叶子节点段申请X、Y、Z
所以非叶子节点和叶子节点所在区是不一样的,因为他们所属的段不同
段去申请区,一个区包含64个连续的页

下面这个图很形象

在这里插入图片描述

有一种例外,就是当一棵树节点很少,会使用碎片区,该区可能包含多个段的页,即叶子节点和非叶子节点在一页的情况(了解即可)

架构

MySQL5.5版本开始,默认使用InnoDB存储引擎,它擅长事务处理,具有崩溃恢复特性,在日常开发中使用非常广泛。
下面是InnoDB架构图,左侧为内存结构,右侧为磁盘结构
在这里插入图片描述

内存结构

BufferPool缓冲池

:缓冲池可以缓存一些磁盘上经常真实操作页数据(此处使用操作系统的LRU算法来决定那些也存入BufferPool),再统一时刻,将缓冲区中的脏页刷入磁盘,减少cpu直接操作磁盘,增强性能(类似于批量插入)
:也可以从缓冲池读数据,解决了磁盘和内存数据不一致问题,写在缓存,读在缓存

关键特点:

  • 目标是加速数据访问(读和写都依赖 Buffer Pool)。
  • 如果数据页不在 Buffer Pool 中,需要先从磁盘加载到内存,再进行操作。
  • BufferPool存储数据页按照
    在这里插入图片描述
正常查询缓冲池数据如何查询

缓冲池有一个对应的hash表Page Hash Table
可以快速判断某个数据页(由 space_id + page_no 标识)是否已缓存在缓冲池中。
它仅管理页是否在缓冲池,不涉及具体行记录的位置。!!!

虽然说buffer pool的页是链式存储的
但是可以通过它的子页编号来查询缓冲池是否存储该页
如果存储就至改页继续查询
来达到B+树的查询方式

所以还是通过B+树的方式查询,比如说id=1 从根节点到id=1的叶子节点路径上的所有页都在buffer pool即可但在buffer pool中查询到
在这里插入图片描述
deepseek给出的流程,其实和我说的差不多
在这里插入图片描述

这里和下面的AHI有关系

Change Buffer更改缓冲区

针对非唯一二级索引的 INSERT/UPDATE/DELETE 操作,若此时该数据并未在Buffer Pool中,将索引变更暂存到内存(Change Buffer),避免立即写入磁盘。
未来数据被读取,数据页加载到Buffer Pool,Change Buffer对应的修改操作合并到Buffer Pool的对应数据,再一次性写入硬盘(这次写入硬盘的操作可能包含多个DML语句)

关键特点:

  • 目标是减少随机磁盘 I/O(尤其是写操作)。
  • 通过延迟写入,将多次随机 I/O 合并为少量顺序 I/O。

在这里插入图片描述

why需要Change Buffer?

问题:
非唯一二级索引的更新通常是随机 I/O(索引页在磁盘上的位置分散)。
如果每次写入都直接操作磁盘,性能极差,磁针需要移动。

Change Buffer 的优化
多次索引变更暂存到内存,后续合并到 Buffer Pool 中的索引页,再批量刷盘。
例如:100 次 INSERT 操作可能合并为 1 次磁盘写入。

如果没有chage Buffer?
没有的话,因为DML是随机IO,每次我们操作的需要将对应的数据页加载到Buffer Pool,这个过程需要IO操作,随机IO耗时较久,所以将这个操作存储到changer pool,等对应数据页加载到buffer pool时(被读取)再合并,然后刷入磁盘,减少IO;

为什么主键或者唯一索引不用chage Buffer?
因为这些字段必须实时检查唯一性约束,因此索引页必须立即加载到 Buffer Pool 中,无法延迟写入。(加载到buffer pool只要加载进去的话就是唯一的,因为磁盘里有或者buffer pool原本就有都会冲突)
而非唯一二级索引:无需实时检查唯一性,可以安全延迟写入,完美适配 Change Buffer

Adaptive Hash Index 自适应哈希索引

AHI 的目的是加速对已在缓冲池中的热点数据页的访问。,从原来的B+树转换为hash查询,针对于精确匹配(WHERE key = value)
当某些索引值被频繁访问时(如某主键被多次查询),InnoDB会为这些键值在内存中构建哈希条目。
在这里插入图片描述

AHI和Buffer Pool之间一些联系

buffer pool是以线性方式存储页的,但是又是页B+树的方式查询的
AHI里面存储V的是缓冲池中的页号+行号,就可以直接找到对应数据,而不用B+树那样逐层寻找
在这里插入图片描述

log Buffer

redo log和undo log后面会讲解到
在这里插入图片描述

磁盘结构

在这里插入图片描述

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

  • File-Per-Table Tablespaces
    每张表的独立表空间,则每个表的文件表空间包含单个InnoDB表的数据和索引 ,并存储在文件系统上的单个数据文件中。 一个.ibd 对应一个表

  • General Tablespaces 通用表空间
    需要通过 CREATE TABLESPACE 语法创建通用表空间,在创建表时,可以指定该表空间

# 创建通用表空间
CREATE TABLESPACE ts_name ADD DATAFILE 'file_name' ENGINE = engine_name;
# 创建表时指定表空间
CREATE TABLE xxx ... TABLESPACE ts_name;
#-----------举例-----------
create tablespace ts_01 add datafile 'mydb01.ibd' engine = innodb;
# 创建表空间成功后,后续创建表时 可以指定把表创建至该表空间里
use db1;
create table t1(id int primary key auto_increment, name varchar(10)) engine = innodb tablespace ts_01;
  • Undo Tablespaces 撤销表空间
    撤销表空间,MySQL实例在初始化时会自动创建两个默认的undo表空间(初始大小16M),用于存储 undo log日志,undo_001, undo_002
    在这里插入图片描述
  • Temporary Tablespaces 临时会话表空间
    InnoDB 使用会话临时表空间和全局临时表空间。存储用户创建的临时表等数据。
  • Doublewrite Buffer Files 双写缓冲区
    双写缓冲区,innoDB引擎将数据页从Buffer Pool刷新到磁盘前,先将数据页写入双写缓冲区文件中,便于系统异常时恢复数据
  • Redo Log 重做日志,用以实现事务持久性
    在这里插入图片描述

为什么在内存的数据还需要存在磁盘中

比如Change Buffer存储在内存的同时也存储在系统表空间(System Tablespace)
在这里插入图片描述

后台线程

这里介绍的都是将内存结构数据刷新到磁盘所用到的后台线程
在这里插入图片描述

事务原理

事务:一组操作的集合,要么全部成功,要么全部失败:
事务的四大特性:(ACID)原子性,一致性,隔离性,持久性

  • A:事务是不可分割的最小操作单元,要么全部成功,要么全部失败

  • C:事务完成时,必须使所有的数据都保持一致状态

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

  • D:事务一旦提交或回滚,它对数据库中的数据的改变就是永久的

在这里插入图片描述
事务的隔离级别:读未提交,读已提交,可重复读,串行化

redo log保证持久性,记录我们DML语句操作,先将顺序IO的redolog日志刷如磁盘,具体物理数据还在Buffer Pool中,某一时刻,将脏页刷磁盘,刷磁盘出错可以根据redolog日志进行恢复

redo log

  • 持久性redo log,重做日志
    记录事务提交时,对数据页的物理修改,实现事务的持久性
    包含两部分:重做日志缓冲(内存结构中的Log Buffer)与 磁盘的重做日志文件,提交后会把所有修改信息保存到该文件中,用于当刷新脏页到磁盘发生错误时 进行数据恢复使用

update/delete执行过程:
1.先看内存的BufferPool中有没有该页,如果没有该页则通过后台线程从磁盘中把页读到Buffer Pool
2.直接操作缓冲区中的数据,该页变成脏页
3.首先把数据页的物理变化记录在内存中的redologbuffer,commit 事务提交的时候,redologBuffer会直接把数据页变化刷新到磁盘当中,即ib_logfile0,ib_logfile1中
4.在某个时机 脏页以一定频率刷新到磁盘中进行持久化,若此时出错,则可以通过磁盘文件中的redo_log进行数据恢复
注:脏页刷入磁盘的时间点可能是buffer pool空间不足了,也可能是脏页的比例超过一个数值,也可能是定时刷
5.若脏页顺利写入磁盘,则redolog文件就不再需要,因此每过一段时间就清理一次redo log日志,是循环性的,不是永久的

日志文件都是追加的,是顺序磁盘I/O,效率比数据在磁盘的随机存取快速的多,WAL 先写日志 Write-Ahead Logging预写式日志
而数据刷磁盘操作一般都是随机IO效率低,需要定时一起刷入,减少IO操作

在这里插入图片描述

  • 原子性undo log,回滚日志

1.用于记录被修改前的信息,作用包括两个:提供回滚MVCC(多版本并发控制)
undo log 和 redo log 记录的物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的 update记录(执行update之前 数据长的样子)。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚

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

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

MVCC

基本概念

当前读
读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,如:

select ... lgck in share mode(共享锁),
select .. for update
updateinsertdelete(排他锁)

都是一 种当前读。
快照读
简单的select(不加锁)就是快照读,快照读,读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。
Read Committed(读已提交):每次select,都生成一个快照读。
Repeatable Read(可重复读):开启事务后第一个select语句才是快照读的地方。
Serializable(串行化):快照读会退化为当前读。

MVCC(Multi-Version Concurrency Control)

  • 多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,快照读为MySQL实现
  • MVCC提供了一个非阻塞读功能。MVCC的具体实现,还需要依赖于数据库记录中的三个隐式字段、undo log日志、readView

隐藏字段

在这里插入图片描述
当你建立一个表的时候,会正常的给你三个字段,但是他还会生成隐藏的三个分别是上面灰色的部分:DB_TRX_ID, DB_ROLL_PTR, DB_ROW_ID

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

undo log版本链

undo log

  • 回滚日志,在insert、 update、 delete的时候产生的便于数据回滚的日志。
  • insert的时候,产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除。
  • update、delete的时候,产生的undo log日志不仅在回滚时需要,在快照读时也需要,不会立即被删除。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链表,链表的头部是最新的旧记录,链表尾部是最早的旧记录。

read view介绍

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

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

trx_ id: 代表是当前事务ID对应数据项隐藏项的TDB_trx_ id
在这里插入图片描述

解释一下第四项,就是你事务是后开始的,前面的还没提交你就提交了,就会产生第四种结果,也是可读的

不同的隔离级别,生成ReadView的时机不同:
➢READ COMMITTED (读已提交):在事务中每一次执行快照读时生成ReadView。
➢REPEATABLE READ(可重复读):仅在事务中第一次执行快照读时生成ReadView, 后续复用该ReadView。

RC级别,读分析

RC隔离级别下,在事务中每一次执行快照读时生成ReadView。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

RR级别,读分析

RR隔离级别下,仅在事务中第一次执行快照读时生 成ReadView,后续复用该ReadView。
在这里插入图片描述
在这里插入图片描述

相关文章:

  • MySQL死锁:面试通关“三部曲”心法
  • Linux的权限问题
  • 【SPIN】PROMELA语言编程入门同步机制(SPIN学习系列--4)
  • std::ranges::iota
  • R²AIN SUITE 亮相第九届智能工厂高峰论坛
  • [CSS3]属性增强2
  • 卷积神经网络中的局部卷积:原理、对比与应用解析
  • PHP 实现连续子数组的最大和、整数中1出现的次数
  • [ 计算机网络 ] | 宏观谈谈计算机网络
  • Ultralytics YOLO11模型预测初体验(+实例+亲测)
  • OSD原理以及模块的讲解
  • java基础-多态性
  • [[春秋云境] Privilege仿真场景
  • R语言+贝叶斯网络:涵盖贝叶斯网络的基础、离散与连续分布、混合网络、动态网络,Gephi可视化,助你成为数据分析高手!
  • 【成品设计】基于51单片机实物系列项目
  • 什么是Monorepo(单体仓库)(monolithic repository)
  • vuex的基本使用
  • 类和对象(3)--《Hello C++ World!》(5)(C/C++)--构造函数,析构函数和拷贝构造函数
  • JavaWeb:文件上传(本地存储阿里云oss)
  • 【工具推荐】--Git详解
  • 66岁华仁世纪集团有限公司创始人、董事长梁福东逝世
  • 沧州盐碱地“逆天改命”:无用之地变良田,候鸟翔集水草丰美
  • 坐标大零号湾科创策源区,上海瑞金医院闵行院区正式启动建设
  • 广西桂林、百色、河池等地表态:全力配合中央对蓝天立的审查调查
  • 关税影响下沃尔玛想涨价,特朗普施压:自行承担,别转嫁给顾客
  • 圆桌丨全球化博弈与人工智能背景下,企业如何落地合规体系