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

相关推荐
9527华安1 小时前
FPGA多路MIPI转FPD-Link视频缩放拼接显示,基于IMX327+FPD953架构,提供2套工程源码和技术支持
fpga开发·架构·音视频
YashanDB2 小时前
【YashanDB知识库】XMLAGG方法的兼容
数据库·yashandb·崖山数据库
独行soc2 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍11基于XML的SQL注入(XML-Based SQL Injection)
数据库·安全·web安全·漏洞挖掘·sql注入·hw·xml注入
小林coding2 小时前
阿里云 Java 后端一面,什么难度?
java·后端·mysql·spring·阿里云
风间琉璃""3 小时前
bugkctf 渗透测试1超详细版
数据库·web安全·网络安全·渗透测试·内网·安全工具
drebander3 小时前
SQL 实战-巧用 CASE WHEN 实现条件分组与统计
大数据·数据库·sql
IvorySQL3 小时前
IvorySQL 4.0 发布:全面支持 PostgreSQL 17
数据库·postgresql·开源数据库·国产数据库·ivorysql
18号房客3 小时前
高级sql技巧进阶教程
大数据·数据库·数据仓库·sql·mysql·时序数据库·数据库架构
Dawnㅤ3 小时前
使用sql实现将一张表的某些字段数据存到另一种表里
数据库·sql
张声录13 小时前
【ETCD】【实操篇(十二)】分布式系统中的“王者之争”:基于ETCD的Leader选举实战
数据库·etcd