Bootstrap

[翻译] InnoDB 空间文件布局基础

本系列文章翻译自 中的 文章 。共 16 篇,本文为第 3 篇。原文链接:

因翻译水品有限,为了避免对读者造成误解,一些专有名词的翻译会在其后用标记出原文。

InnoDB 空间文件布局基础

)一文中,我介绍了用来记录 内部结构的 项目,本文中所使用的图表均可以在该项目中找到。

的数据存储模型称为“空间”,在 上下文中通常称为“表空间”,而在 本身中有时也称为“文件空间”。一个空间可能由操作系统层面的多个实际文件(例如 、 等)组成,但它们在逻辑上被当作一个文件,多个物理文件被视为是连接在一起的。

为每个 空间 都分配了一个整数的 空间ID[],在许多地方都需要使用 空间ID 来引用 空间。 有一个“系统空间”,它的 空间ID 固定为。系统空间 用于记录 需要的各种特殊簿记[]。在 中,除了系统空间, 目前只支持形式的空间,这会为每张表创建一个文件。在内部,这个 文件实际上是一个功能齐全的空间,可以包含多张表,但在 的实现中,一个文件只包含一个表。

页面

每个空间都被划分为许多个页面,通常每个页面的大小为 (这个页面大小可能因为两方面影响而有所变化:编译时修改了 定义的值,或者使用了 压缩)。 为空间中的每个页面都分配了一个的整数页码,通常称为“偏移量”,这实际上只是这个页面 从空间开始位置 的偏移量(因为对于多个文件组成的空间来说,并不一定是 从文件开始位置 的偏移量)。因此,号页面 位于偏移量为的位置,号页面 位于偏移量为的位置,等等。(有的读者可能知道 有一个数据大小限制是,这实际上是每个空间的大小限制,主要是由于页面号是一个的整数,结合默认的页面大小可以得到:232 x 16 KB = 64 TB)

译者注:这里的空间大小限制其实还取决于页面的大小,表空间的最大限制 = 2^32 x 页面的大小。官方文档对此也有说明:

一个页面的基本布局如下:

每个页面都有一个 的 和 的 ( 是“”的缩写)。中包含一个字段,表示页面类型,对于页面其余部分,不同类型的页面具有不同的结构。和的详细结构如下:

  • :页面类型存储在 中。因为页面被用于 文件空间管理、区段管理、事务系统、数据字典、回滚日志[]、 二进制大对象[],还有索引(也就是表的数据)等多种用途,不同的用途的页面可能结构不同,所以为了解析页面数据,必须要有页面类型这个字段。

  • :当前页面所属空间的空间ID。

  • :页码。当页面被初始化后,页码就会存储在中。通过比较 “从该字段读取的页码” 与 “基于文件偏移量的页码” 是否匹配,可以检验页面读取是否正确,并且这个字段被初始化同时就表明页面已经被初始化。

  • & :一个位的校验和存储在中,一个旧格式[]的(且是破损的)位校验和存储在中。这个旧格式的校验和在将来可能会被弃用,其空间可能被回收

  • & :相同类型页面的逻辑上一页和下一页的指针存储在中。这两个指针是用来构建双向链表的,用于将同一层级的类型页面连接起来,这在进行范围扫描的时候是非常有效的,例如全索引扫描。但许多类型的页面其实都不使用这两个字段。

  • & :页面最后一次修改的日志序列号(简写为,64位整数)存储在中,并且同一 的低位存储在中。

  • :一个位的 字段存储在中,实际上整个系统中只有 号空间的号页面 使用该字段,这个字段记录了整个系统(所有的空间)中刷新到页面中的最高 。这个字段非常适合在其余空间中用于其他用途。

译者注:

  • 校验和是用来检验从磁盘中读入内存的一个页面是否损坏的一种机制。写入页面时计算 校验和 写入页面中,当读出页面时再次计算校验和,如果校验和与页面中存储的校验和一致,则说明没有损坏,否则说明页面有损坏。

  • InnoDB有三种校验算法:、、,可以通过 系统变量 来指定,它们之间的区别可以参考官方文档:

  • 当校验算法为和时, 和 中的两个校验和字段的值是相同的,而当校验和为时,两个校验和字段时不同的。

空间文件

一个空间文件是由许多个页面(最多 232 个)连接而成。为了提高管理效率,这些页面被划分为大小的块(页面大小为 的情况下一块为 个连续页面),称为“区段”。许多结构都只按照“区段”为单位在空间内分配页面。

需要使用一些簿记信息来跟踪所有的页面、区段以及空间本身,因此空间文件中有一些必需的“超级结构[]”:

空间中的第一个页面(号页面)固定为 (的简写)页面。页面中 包含一个 结构(名字可能容易混淆),用于跟踪空间大小 以及 区段链表 、 区段链表 和 区段链表 等内容。(关于空闲空间管理将在以后的文章中进行更详细的讨论)

一个 页面内部的空间仅能够存储 个区段( 页, MB)的簿记信息,因此需要每隔 页使用额外的空间来存储 页面用以记录区段的簿记信息。 页面 和 页面的结构是相同的,唯一的区别是 在 页面中, 结构是置为零不使用的。随着空间文件的增长,这些额外的页面会自动分配。

空间中的第三个页面(号页面)是一个 页面,用于存储与文件段相关的列表(文件段可以理解为 区段组成的组 再加上 单独分配的“碎片”页面 组成的数组)。每个 页可以存储个 条目,每个索引需要两个 条目。(关于 条目和 的内容将在以后的文章进行更详细地讨论)

除了每个 页面 和 页面外,还有 页面,用于与插入缓冲[]相关的簿记信息,这不在本文讨论范围之内。

译者注:插入缓冲[] 又叫做 写缓冲[],主要用于加速对数据的变更操作,例如、、。官方文档:

系统空间

在 中,系统空间[](空间ID为)是比较特殊的,它包含了许多分配在固定页码上的页面,用于存储对 的操作至关重要的大量信息。系统空间与其他空间一样,它的前三个页面分配了 、 和 页面。除此之外,它还有一些其他的特殊页面:

译者注:图中是系统表空间在磁盘上对应的文件名

系统表空间中分配了以下页面:

  • 号页面,类型为:与插入缓冲有关的头部和簿记信息

  • 号页面,类型为:用于插入缓冲的索引树的根页面

  • 号页面,类型为:存储与 事务系统的操作有关的信息,例如最新的事务、 相关的信息以及 所在区段的位置

  • 号页面,类型为:第一个回滚段的页面。会根据需要分配额外的页面(或整个区段)来存储回滚段数据

  • 号页面,类型为:与数据字典相关的头部信息,包含组成数据字典的索引的根页码。通过这些信息能够找到任何其他索引 ,因为它们的根页码存储在数据字典中

  • -号页面: 中的第一块(个页面,一个区段)。 是 崩溃恢复机制的一部分

  • -号页面: 中的第二块

除了这些特殊的页面之外,其他页面都会根据需要分配给索引、回滚段、撤消日志[]等。

独立表空间文件

提供了一个特性,它能够为每个创建的 表创建一个文件。正如前文所述,这实际上是为每个表创建一个空间,所以这个特性的一个更好的名称应该是“”,而不是“”。为每个表创建的文件具有典型的空间文件结构:

在必要的个初始页面之后,接下来空间中分配的页面是表中每个索引的根页面,按照它们在表创建时定义的顺序排序(这里不考虑表创建之后添加索引的所涉及的特性)。号页面是聚簇索引的根页面,号页面页是第一个二级索引的根页面,等等。

译者注: 是在中引入的新特性,主要用于加速二级索引的创建和删除,即在创建表之后添加或者删除二级索引时不需要重建整张表。在中,该特性变得更加通用,更多的种类的操作都可以在不复制整张表或者不阻塞 操作的情况下执行,所以在中这个特性被称作。相关文档:

由于 的大部分簿记结构都存储在系统空间中,因此在独立表空间中分配的大部分页面都是 类型的页面用于存储表数据。

下一步是什么

接下来,我们将研究 中的空闲空间管理: 区段描述符、文件段()以及一系列链表结构。