写点什么

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

用户头像
keaper
关注
发布于: 47 分钟前
[翻译] InnoDB 空间文件布局基础

本系列文章翻译自 Jeremy Cole's Blog 中的 InnoDB系列 文章 。共 16 篇,本文为第 3 篇。原文链接:The basics of InnoDB space file layout


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

InnoDB 空间文件布局基础

On learning InnoDB: a journey to the core译文)一文中,我介绍了用来记录 InnoDB 内部结构的 innodb_diagrams 项目,本文中所使用的图表均可以在该项目中找到。


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


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

页面

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


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


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



每个页面都有一个 38字节FIL Header8字节FIL TrailerFIL 是“File”的缩写)。FILE Header中包含一个字段,表示页面类型,对于页面其余部分,不同类型的页面具有不同的结构。FIL HeaderFIL Trailer的详细结构如下:



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

  • Space ID(4):当前页面所属空间的空间 ID。

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

  • Checksum(4) & Old-style Checksum(4):一个32位的校验和存储在FIL Header中,一个旧格式[older format]的(且是破损的)32位校验和存储在FIL Trailer中。这个旧格式的校验和在将来可能会被弃用,其空间可能被回收

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

  • LSN for last page modification(8) & Low 32 bits of LSN(4):页面最后一次修改的日志序列号(简写为LSN,64 位整数)存储在FIL Header中,并且同一 LSN 的低32位存储在FIL Trailer中。

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


译者注:

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

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

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

空间文件

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


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



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


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


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


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


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

系统空间

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



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


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


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

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

  • 5号页面,类型为TRX_SYS:存储与 InnoDB 事务系统的操作有关的信息,例如最新的事务IDMySQL Bin Log相关的信息以及 Double Write Buffer 所在区段的位置

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

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

  • 64-127号页面:Double Write Buffer 中的第一块(64个页面,一个区段)。Double Write BufferInnoDB 崩溃恢复机制的一部分

  • 128-191号页面:Double Write Buffer 中的第二块


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

独立表空间文件

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



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


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

  1. Chapter 2. Fast Index Creation in the InnoDB Storage Engine

  2. Fast Index Creation

  3. 14.13 InnoDB and Online DDL


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

下一步是什么

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

发布于: 47 分钟前阅读数: 4
用户头像

keaper

关注

还未添加个人签名 2018.01.19 加入

还未添加个人简介

评论

发布
暂无评论
[翻译] InnoDB 空间文件布局基础