Mysql是怎样运行之InnoDB数据页结构

898 阅读5分钟

数据页结构的快速浏览

页的本质就是一块16KB大小的存储空间,InnoDB为了不同的目的而把页分为不同的类型,比如存放表空间头部信息的页,存放 Insert Buffer信息的页,存放 INODE 信息的页,存放 undo 日志信息的页等等。数据页代表的这块16KB大小的存储空间可以被划分为多个部分,不同部分有不同的功能,各个部分如图所示:

页.webp

名称中文名占用空间大小简单描述
File Header文件头38字节一些描述页的信息
Page Header页头56字节页的状态信息
Infimum + Supremum最小记录和最大记录26字节两个虚拟的行记录
User Records用户记录不确定实际存储的行记录内容
Free Space空闲空间不确定页中尚未使用的空间
Page Directory页目录不确定页中的记录相对位置
File Trailer文件结尾8字节校验页是否完整

记录在页中的存储

在页的7个组成部分中,我们自己存储的记录会按照我们指定的行格式存储到User Records部分。是在一开始生成页的时候,其实并没有User Records这个部分,每当我们插入一条记录,都会从Free Space部分,也就是尚未使用的存储空间中申请一个记录大小的空间划分到User Records部分,当Free Space部分的空间全部被User Records部分替代掉之后,也就意味着这个页使用完了,如果还有新的记录插入的话,就需要去申请新的页了,这个过程的图示如下:

页中记录.webp

不管我们向页中插入了多少自己的记录,InnoDB都规定他们定义的两条伪记录分别为最小记录与最大记录。这两条记录的构造十分简单,都是由5字节大小的记录头信息和8字节大小的一个固定的部分组成的,如图所示

伪记录.webp

Page Directory

Page Directory 即页目录,相当于对User Record的真实行记录创建的一个稀疏目录。当User Record中的记录比较多时,查询数据将会耗时增多(尤其是在行记录之间是以链表的形式来存储的)。因此,有了Page Dircetory,我们把User Record分为n个段,并将每一段的第一个行记录的RowID的第一个字节的**相对地址(相对于页的起始地址)**用2个字节存放在Page Directory中,称这个相对地址(指针)为槽(Slots),那么分为n个段,则Page Directory中将存放n个槽。如此,可以先在Page Directory中用二分法缩小查询范围,再在User Record中顺序查找相应记录,缩短了查询时间。

页目录.webp

注意行格式中的头信息中的n_owned属性

Page Header

Page Header描述的是内的各种状态信息,比方说页里头有多少个记录了呀,有多少个槽等。

名称占用空间大小描述
PAGE_N_DIR_SLOTS2字节在页目录中的槽数量
PAGE_HEAP_TOP2字节第一个记录的地址
PAGE_N_HEAP2字节本页中的记录的数量(包括最小和最大记录以及标记为删除的记录)
PAGE_FREE2字节指向可重用空间的地址(就是标记为删除的记录地址)
PAGE_GARBAGE2字节已删除的字节数,行记录结构中delete_flag为1的记录大小总数
PAGE_LAST_INSERT2字节最后插入记录的位置
PAGE_DIRECTION2字节最后插入的方向
PAGE_N_DIRECTION2字节一个方向连续插入的记录数量
PAGE_N_RECS2字节该页中记录的数量(不包括最小和最大记录以及被标记为删除的记录)
PAGE_MAX_TRX_ID8字节修改当前页的最大事务ID,该值仅在二级索引中定义
PAGE_LEVEL2字节当前页在索引树中的位置,高度
PAGE_INDEX_ID8字节索引ID,表示当前页属于哪个索引
PAGE_BTR10字节非叶节点所在段的segment header,仅在B+树的Root页定义
PAGE_LEVEL10字节B+树所在段的segment header,仅在B+树的Root页定义

File Header

File Header描述的就是外的各种状态信息,比方说这个页的编号是多少,它的上一个页、下一个页等。File HeaderInnoDB页的第一部分,这个部分占用固定的38个字节。

名称占用空间大小描述
FIL_PAGE_SPACE_OR_CHKSUM4字节页的校验和(checksum值)
FIL_PAGE_OFFSET4字节页号
FIL_PAGE_PREV4字节上一个页的页号
FIL_PAGE_NEXT4字节下一个页的页号
FIL_PAGE_LSN8字节最后被修改的日志序列位置(英文名是:Log Sequence Number)
FIL_PAGE_TYPE2字节该页的类型
FIL_PAGE_FILE_FLUSH_LSN8字节仅在系统表空间的一个页中定义,代表文件至少被更新到了该LSN值,独立表空间中都是0
FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID4字节页属于哪个表空间

FIL_PAGE_TYPE

名称十六进制描述
FIL_PAGE_ALLOCATED0x0000最新分配,还没使用
FIL_PAGE_UNDO_LOG0x0002Undo Log页
FIL_PAGE_INODE0x0003段信息的节点
FIL_PAGE_IBUUF_FRE_LIST0x0004Insert Buffer空闲列表
FIL_PAGE_IBUF_BITMAP0x0005Insert Buffer位图
FIL_PAGE_TYPE_SYS0x0006系统页
FIL_PAGE_TYPE_TRX_SYS0x0007事务系统数据
FIL_PAGE_TYPE_FSP_HDR0x0008File Space Header
FIL_PAGE_TYPE_XDES0x0009扩展描述页
FIL_PAGE_TYPE_BLOB0x000ABLOB页
FIL_PAGE_INDEX0x45BFB+树的子节点

File Trailer

每页最后8字节为File Trailer部分,这部分是为了保证页的完整性。 前四个字节为checksum校验和,需要通过crc32(默认)算法与File Header中的FIL_PAGE_SPACE_OR_CHKSUM比较。 后四个字节要与File Header中的FIL_PAGE_LSN值比较。

备注

MySQL 是怎样运行的第5章