【MySQL进阶】InnoDB引擎存储结构和架构

文章目录

逻辑存储结构

  1. 表空间(Tablespaces):InnoDB使用表空间来管理存储表和索引的数据文件。每个表空间包含一个或多个数据文件,这些文件实际上存储数据表和索引。
  2. 段(Segments):InnoDB将每个表空间划分为多个段,用于存储不同类型的数据。主要的段类型包括数据段、索引段、回滚段和系统段。数据段就是B+树的叶子节点, 索引段即为B+树的 非叶子节点。
  3. 区(Extent):每个段由一组区组成,每个区的大小通常为1MB。区是InnoDB中进行磁盘读写的最小单元,它包含了一组连续的数据页。
  4. 页(Page):区又由一组页组成,通常为16KB大小。页是InnoDB存储数据的最小单位,它可以包含表的行数据、索引数据以及其他管理信息。
  5. 行(Row):InnoDB使用"B+树"索引结构来组织数据。数据行存储在表的叶子页中,每一行代表一条记录。行数据包括所有列的值以及一些额外的管理信息。
  • x_id:每次对某条记录进行改动时,都会把对应的事务id赋值给trx_id隐藏列。
  • Roll_pointer:每次对某条引记录进行改动时,都会把旧的版本写入到undo日志中,然后这个隐藏列就相当于一个指针,可以通过它来找到该记录修改前的信息。
  1. 索引(Index):InnoDB使用聚集索引的方式来存储数据。每个InnoDB表都有一个主键索引,它决定了数据的物理存储顺序,并且作为其他非主键索引的查找入口。除了主键索引外,InnoDB还支持创建其他非主键索引,这些索引通常会占用额外的存储空间。

架构

MySQL5.5 版本开始,默认使用InnoDB存储引擎,它擅长事务处理,具有崩溃恢复特性,在日常开发

中使用非常广泛。下面是InnoDB架构图,左侧为内存结构,右侧为磁盘结构

内存结构

我们先来看看内存结构

主要分为这么四大块儿: Buffer Pool、Change Buffer、Adaptive Hash Index、Log Buffer。

Buffer Pool&Adaptive Hash Index

Buffer Pool 本质上是 InnoDB 向操作系统申请的一段连续的内存空间。InnoDB 的数据是按数据页为单位来读写,每个数据页的大小默认是 16KB。数据是存放在磁盘中,每次读写数据都需要进行磁盘 IO 将数据读入内存进行操作,效率会很低,所以提供了 Buffer Pool 来暂存这些数据页,缓存中的这些页又叫缓冲页。缓冲页的数据会以一定的频率刷新到磁盘中,减少了IO。

工作原理:

  • 从数据库读取数据时,会首先从缓存中读取,如果缓存中没有,则从磁盘读取后放入 Buffer Pool
  • 向数据库写入数据时,会写入缓存,缓存中修改的数据会定期刷新到磁盘,这一过程称为刷脏

Buffer Pool 以Page页为单位,每个缓冲页都有对应的控制信息,包括表空间编号、页号、偏移量、链表信息等,控制信息存放在占用的内存称为控制块,控制块与缓冲页是一一对应的,但并不是物理上相连的,都在缓冲池中。底层采用链表数据结构管理Page。

根据状态,将Page分为三种类型:

  • free page:空闲page,未被使用。
  • clean page:被使用page,数据没有被修改过。
  • dirty page:脏页,被使用page,数据被修改过,也中数据与磁盘的数据产生了不一致。

MySQL 提供了缓冲页的快速查找方式:哈希表,使用表空间号和页号作为 Key,缓冲页控制块的地址作为 Value 创建一个哈希表,获取数据页时根据 Key 进行哈希寻址:

  • 如果不存在对应的缓存页,就从 free 链表中选一个空闲缓冲页,把磁盘中的对应页加载到该位置
  • 如果存在对应的缓存页,直接获取使用,提高查询数据的效率

Change Buffer

InnoDB 管理的 Buffer Pool 中有一块内存叫 Change Buffer 用来对增删改操作提供缓存,可以通过参数来动态设置,设置为 50 时表示 Change Buffer 的大小最多占用 Buffer Pool 的 50%

  • 唯一索引的更新不能使用 Change Buffer,需要将数据页读入内存,判断没有冲突在写入
  • 普通索引可以使用 Change Buffer,直接写入 Buffer 就结束,不用校验唯一性

Change Buffer 并不是数据页,只是对操作的缓存,所以需要将 Change Buffer 中的操作应用到旧数据页,得到新的数据页(脏页)的过程称为 Merge

  • 触发时机:访问数据页时会触发 Merge、后台有定时线程进行 Merge、在数据库正常关闭(shutdown)的过程中也会触发
  • 工作流程:首先从磁盘读入数据页到内存(因为 Buffer Pool 中不一定存在对应的数据页),从 Change Buffer 中找到对应的操作应用到数据页,得到新的数据页即为脏页,然后写入 redo log,等待刷脏即可

说明:Change Buffer 中的记录,在事务提交时也会写入 redo log,所以是可以保证不丢失的

业务场景:

  • 对于写多读少的业务来说,页面在写完以后马上被访问到的概率比较小,此时 Change Buffer 的使用效果最好,常见的就是账单类、日志类的系统
  • 一个业务的更新模式是写入后马上做查询,那么即使满足了条件,将更新先记录在 Change Buffer,但之后由于马上要访问这个数据页,会立即触发 Merge 过程,这样随机访问 IO 的次数不会减少,并且增加了 Change Buffer 的维护代价

补充:Change Buffer 的前身是 Insert Buffer,只能对 Insert 操作优化,后来增加了 Update/Delete 的支持,改为 Change Buffer。

下面是 InnoDB 存储引擎中修改数据的工作流程:

  1. 写操作:当有一个写操作需要修改某个非唯一索引时,例如插入、更新或删除操作,InnoDB 将首先将这个修改操作记录在 Change Buffer 中。
  2. Buffer Pool 中的修改:同时,InnoDB 会将被修改的数据页(包括索引页和数据页)加载到 Buffer Pool 中进行修改。在 Buffer Pool 中进行修改操作可以获得更快的访问速度和更低的 I/O 开销。
  3. 脏页标记:当数据页在 Buffer Pool 中被修改后,会被标记为 "dirty",表示该页已被修改,需要在未来的某个时间点写回到磁盘。
  4. 脏页刷入:InnoDB 会异步进行脏页的刷入操作。这个过程称为 "flush",通常由后台线程或异步刷新操作来完成。在刷入过程中,脏页的修改将被写回到磁盘上的对应数据文件中。
  5. 读操作:当其他查询或读取需要访问被修改的记录时,InnoDB 首先检查 Buffer Pool 中是否存在所需数据页。如果存在,数据将直接从 Buffer Pool 中获取。如果数据不在 Buffer Pool 中,则需要从磁盘读取对应的数据页到 Buffer Pool 中,然后再返回结果。

Log Buffer

Log Buffer:日志缓冲区,用来保存要写入到磁盘中的log日志数据(redo log 、undo log),

默认大小为 16MB,日志缓冲区的日志会定期刷新到磁盘中。如果需要更新、插入或删除许多行的事

务,增加日志缓冲区的大小可以节省磁盘 I/O。

参数:

innodb_log_buffer_size:缓冲区大小

innodb_flush_log_at_trx_commit:日志刷新到磁盘时机,取值主要包含以下三个:

  • 1: 日志在每次事务提交时写入并刷新到磁盘,默认值。
  • 0: 每秒将日志写入并刷新到磁盘一次。
  • 2: 日志在每次事务提交后写入,并每秒刷新到磁盘一次。

磁盘结构

  1. System Tablespace(系统表空间): 系统表空间是数据库管理系统(DBMS)中的一个重要组件。它包含了系统表、用户表的元数据以及其他系统级数据。系统表空间通常以文件的形式存在,例如在MySQL中,系统表空间通常是由一个或多个.ibd或.frm文件组成。系统表空间对于数据库的正常运行至关重要。

  2. File-Per-Table Tablespaces(独立表空间): 在一些数据库系统(如MySQL的InnoDB存储引擎)中,可以配置为每个表使用独立的表空间文件。这种配置方式称为"File-Per-Table"。每个表拥有自己的表空间文件,包括数据和索引。这种设计使得表的备份和恢复更加方便,并提供更好的性能和扩展性,同时减少数据碎片化的问题。

  3. General Tablespaces(通用表空间): 通用表空间是MySQL 5.7版本中引入的特性。通用表空间允许将多个表存储在一个或多个共享表空间文件中。这种方式便于管理和维护数据库对象,可以更灵活地进行数据迁移和备份。

  4. Undo Tablespaces(撤消表空间): 撤消表空间用于存储事务的撤消日志,也被称为回滚日志。在数据库中,事务修改数据时,撤消日志记录了对数据所做的修改,以便在回滚操作或崩溃恢复时撤销或恢复事务。

  5. Temporary Tablespaces(临时表空间): 临时表空间用于存储临时表、排序和哈希操作等过程中的临时数据。这些临时数据在操作完成后会自动清除,临时表空间通常具有较高的性能要求。

  6. Doublewrite Buffer Files(双写缓冲): 双写缓冲是InnoDB存储引擎中的一项机制,用于提高数据的写入可靠性。当InnoDB执行写入操作时,会先将数据写入双写缓冲区(一个内存缓冲区),然后再异步地将数据写入磁盘,以保证数据的一致性和可靠性。

  7. Redo Log(重做日志): 重做日志是数据库管理系统中的一种日志机制,用于记录已经发生的事务操作。在数据库发生故障或崩溃时,通过重做日志可以将未提交的事务重新应用到数据库,恢复到故障发生前的状态。重做日志通常以文件的形式存在,是数据库持久性和可恢复性的重要保障。

相关推荐
apcipot_rain1 小时前
【应用密码学】实验五 公钥密码2——ECC
前端·数据库·python
互联网搬砖老肖2 小时前
Web 架构之攻击应急方案
前端·架构
zizisuo2 小时前
9.3.云原生架构模式
云原生·架构
辛一一4 小时前
neo4j图数据库基本概念和向量使用
数据库·neo4j
巨龙之路5 小时前
什么是时序数据库?
数据库·时序数据库
蔡蓝5 小时前
binlog日志以及MySQL的数据同步
数据库·mysql
是店小二呀6 小时前
【金仓数据库征文】金融行业中的国产化数据库替代应用实践
数据库·金融·数据库平替用金仓·金仓数据库2025征文
炒空心菜菜6 小时前
SparkSQL 连接 MySQL 并添加新数据:实战指南
大数据·开发语言·数据库·后端·mysql·spark
专注于大数据技术栈6 小时前
Mac上安装Mysql的详细步骤及配置
mysql
多多*6 小时前
算法竞赛相关 Java 二分模版
java·开发语言·数据结构·数据库·sql·算法·oracle