ibd文件结构

MySQL版本为8.0

组成表空间的各个单位

查看源图像

上图是一张经典的关于页,区,段之间关系的视图,一个区由页组成,一个段由多个区组成。其中段是管理页的逻辑单位,有叶子节点段,非叶子节点段还有回滚段。区是地址连续的物理单位。

对于这张图,我们还需要一些解释,一个段中的不同区物理上不一定连续,且一个段可能只包含一个区中的一个页,而不是整个区(如果这个区专门用来分配碎片页的话)。

区与区之间地址连续,区可以属于一个段,也可以属于表空间。

初看IBD文件

img

默认情况下一个页的大小是16KB,下文也使用默认的页大小。dict_build_tablespace_for_table函数会创建文件并分配FIL_IBD_FILE_INITIAL_SIZE=7个页的空间。

/* We create a new single-table tablespace for the table.

We initially let it be 4 pages:

- page 0 is the fsp header and an extent descriptor page,

- page 1 is an ibuf bitmap page,

- page 2 is the first inode page,

- page 3 will contain the root of the clustered index of

the table we create here. */

之前提到过,区是页管理的物理单位,当页大小为16KB时,区大小为64个页。并且每16K(这个值恒等于页大小)个页就有一个区描述符页(extent descriptor page)。page 0 是表空间头页,也是区描述页,在介绍page 0的字段前,我们先来看一下文件头。

Fil Header

其实我觉得文件头可以回来再看,大家先跳过吧23333。

下图(绿绿的图都是)来自leviathan。对于每个页都有以下的文件头,占据38字节,以及8字节的文件尾。

innodb_page_layout

其中各个字段的意思引用自jcole

  • The page type is stored in the header. This is necessary in order to parse the rest of the page data. Pages are allocated for file space management, extent management, the transaction system, the data dictionary, undo logs, blobs, and of course indexes (table data).
  • The space ID is stored in the header.
  • The page number is stored in the header once the page has been initialized. Checking that the page number read from that field matches what it should be based on the offset into the file is helpful to indicate that reading is correct, and this field being initialized indicates that the page has been initialized.
  • A 32-bit checksum is stored in the header, and an older format (and broken) 32-bit checksum is stored in the trailer. The older checksum could be deprecated and that space reclaimed at some point.
  • Pointers to the logical previous and next page for this page type are stored in the header. This allows doubly-linked lists of pages to be built, and this is used for INDEX pages to link all pages at the same level, which allows for e.g. full index scans to be efficient. Many page types do not use these fields.
  • The 64-bit log sequence number (LSN) of the last modification of the page is stored in the header, and the low 32-bits of the same LSN are stored in the trailer.
  • A 64-bit “flush LSN” field is stored in the header, which is actually only populated for a single page in the entire system, page 0 of space 0. This stores the highest LSN flushed to any page in the entire system (all spaces). This field is a great candidate for re-use in the rest of the space.

FSP Header(page 0)

FSP Header中字段的释义大多可以在源码fsp0fsp.h:130中找到。在继续介绍之前,我们需要先解决这个问题,一个页,在内存中,可以用指针直接获取其内容。但如果是磁盘上的页呢?

InnoDB使用了fil_addr_t这个类型表示,这个类型占据6个字节,前4个字节表示页序号,后2个字节表示页内偏移。

Macro bytes Desc
FIL_ADDR_PAGE 4 Page No
FIL_ADDR_BYTE 2 Page内的偏移量

在FSP Header页中,如下图所示蓝色的字段,比如FSP_FREEFSP_FREE_FRAG都是FLST_BASE_NODE,占用16个字节。

Macro bytes Desc
FLST_LEN 4 存储链表的长度
FLST_FIRST 6 指向链表的第一个节点
FLST_LAST 6 指向链表的最后一个节点

XDES Entry页描述符中 FLST_PREV,和FLST_NEXT都是fil_addr_t类型。

file_list

img

上图是FSP_Header中的各个字段,我们此处先观察XDES Entry,在这里每个XDES Entry占据40字节。每个字段的意思分别是:

  1. XDES ID 所属segment的id;如果没有则值为0,表示属于表空间,位于FSP_FREEFSP_FREE_FRAGFSP_FULL_FRAG链表中的一个。
  2. FLST_PREV 类型就是fil_addr_t,指向所在链表前一个XDES Entry中的FLST_PREV(不是指向XDES_ID字段)。
  3. FLST_PREVFLST_NEXT 在代码中合为XDES_FLST_NODE
  4. XDES_STATE 表示当前的区描述符的状态,位于表空间还是属于段,碎片页还是已经被完全使用。
  5. XDES_BITMAP为16Bytes16 * 8bits,其中一个Page占用两个bit用来表示Page是否被占用。
  • FSP_SPACE_ID表示该Tablespace的ID
  • FSP_SIZE表示目前Tablespace有多少个Page
  • FSP_FREE_LIMIT表示目前在空闲的Extent上最小的尚未被初始化的PagePage Number
  • FSP_SPACE_FLAGS表示Tablespace的标志位
  • FSP_FRAG_N_USED表示FSP_FREE_FRAG中已经使用的Page数量
  • FSP_FREE表示所有的Page均为空闲的Extent
  • FSP_FREE_FRAG表示Extent中尚有Page未被使用
  • FSP_FULL_FRAG表示Extent的所有的Page均已被使用
  • FSP_SEG_ID表示下一个未被使用的Segment ID
  • FSP_SEG_INODES_FULL表示Segment Page的所有的Inode均已被使用
  • FSP_SEG_INODES_FREE表示Segment Page存在空闲的Inode

Inode Page(Page 2)

Tablespace的第三个Page是关于Segment信息的,类型为FIL_PAGE_INODE,其中一个Inode可以理解为管理一个Segment元信息单元:

下图38字节偏移开始的字段为FSEG_INODE_PAGE_NODE,和XDES_FLST_NODE功能相同,即2个fil_addr_t,分别指向前后两个Inode Page。

innodb_space_page_2

在一个Inode即一个Segment中:

  • FSEG_ID表示SegmentID
  • FSEG_NOT_FULL_N_USED表示Segment中被使用的Page数量
  • FSEG_FREE表示所有Page均为空闲的Extent
  • FSEG_NOT_FULL表示部分Page空闲的Extent
  • FSEG_FULL表示所有Page均被使用的Extent
  • FSEG_MAGIC_N表示一个magic numbe用于Debug
  • Slot表示一个Page

页,段,区的关系

InnoDB 表空间page管理

参考资料

《InnoDB 表空间》 淘宝数据库内核月报

《InnoDB 文件组织结构》 Leviathan

《the-basics-of-innodb-space-file-layout》 jcole

posted @ 2021-02-25 00:11  dewxin  阅读(405)  评论(0编辑  收藏  举报