• 数据页页结构总览
  • 记录在页中怎么存储的
  • 记录的头信息
  • deleted_flag
  • min_rec_flag
  • n_owned
  • heap_no
  • record_type
  • next_record
  • Page Directory
  • Page Header
  • File Header
  • File Tailer


Innodb设计了不同类型的页结构,存放表空间头部信息的页、存放change buffer信息的页、存放inode信息的页、存放undo redo日志信息的页;今天我们了解存放记录信息的页(数据页也叫索引页)

数据页页结构总览

MYSQL undo 设置 mysql undo页_mysql

名称

描述

filer header

页的一些通用信息

page header

数据页专有的一些信息

infimum + supremum

两个虚拟的记录

user records

用户存储的记录内容

free space

页中尚未使用的空间

page directory

页中某些记录的相对位置

file tailer

校验也是否完整

记录在页中怎么存储的

MYSQL undo 设置 mysql undo页_数据库_02

记录的头信息

上节已经介绍过记录的头信息结构了,我们重点介绍一些各个结构的具体作用

deleted_flag

主要用来标示当前记录是否被删除。占用一个bit。0-代表未删除;1-代表已删除。
要注意的一点是,打上标记的记录并不会真正被删除,而是加入到垃圾链表,等到下次有相同位置的数据插入就可以复用,而且还能避免删除记录造成的数据页重新排列(消耗性能)

min_rec_flag

B+数每层非叶子结点中最小的目录项记录都会添加该标示

n_owned

一个页面中的记录会被分成很多组(利用分组二分法加快页中的记录查找,不用从第一条遍历到最后一条来查找),每个组中最后一个记录的n_owned代表组中的记录条数,其余的记录n_owned值都为0;记录是怎么样的呢,看下图

MYSQL undo 设置 mysql undo页_MYSQL undo 设置_03


一个数据页16k,可以存储很多条记录,如果通过索引定位到了记录在某一页,然后遍历整个页面来查找记录,复杂度就太高了。所以设计了分组的概念,这样就可以通过page directory中记录的槽信息利用二分法来查找了:

  1. 初始条件下只有两个记录infimum 和 supremum,分别处于两个组,page directory就是记录这些组中的记录偏移量的。
  2. 当一个组中的记录超过8条后,就会拆分两个组,原来的组变成4个,新增的组变成5个,也会在页目录中新增一个槽,记录这个新增组中最大那条记录的偏移量。

MYSQL undo 设置 mysql undo页_database_04

heap_no

标示当前记录在页面堆中的相对位置

record_type

记录类型 0-普通记录 1-B+数非叶子结点的记录 2-表示Infimum记录 3-表示Superemum记录

next_record

下一条记录的相对位置,指向的如上图中是头信息和实际数据之间的位置,这就是记录存储结构设计的巧妙之处了,往左可以读取到记录的头信息,变长字段长度信息,null值列表信息,往右是真实数据。前面还说过变长字段长度信息,null值列表信息这些都是逆序存储的。这样记录中位置靠前的字段和他们的长度信息距离更新,可以提高cpu高速缓存的命中率。

Page Directory

如上图记录存放分组的槽,用来二分法快速查找数据页中的记录

Page Header

类似于继承关系的抽象file header和file tailer是每个数据页都有的结构,定义了一些通用结构,而page header是不同的数据页有自己不同的实现

名称

大小(字节)

描述

PAGE_N_DIR_SLOTS

2

页目录中的槽数量

PAGE_HEAP_TOP

2

还未使用的空间最小地址,该地址之后就是free space

PAGE_N_HEAP

2

第一位表示是否是紧凑型记录,剩余15位表示本页的堆中记录的数据(包含infimum、supremum以及标记为已删除的记录)

PAGE_FREE

2

已删除的记录会通过next_record组成一个单向链表,可以被重新利用

PAGE_GARBAGE

2

已删除记录占用的字节数

PAGE_LAST_INSERT

2

最后插入记录的位置

PAGE_DIRECTORY

2

记录插入的方向

PAGE_N_DIRECTORY

2

一个方向连续插入记录的数量

PAGE_N_RECS

2

该页面中包含的记录的数量(不包含infimum、supremum以及标记为已删除的记录)

PAGE_MAX_TRX_ID

8

修改当前页的最大事务id,仅在二级索引页面中定义

PAGE_LEVEL

2

当前页在B+树中所处的层级

PAGE_INDEX_ID

8

索引id表示当前页属于哪个索引

PAGE_BTR_SEG_LEAF

10

B+树叶子节点段的头部信息,仅在B+树的根页面中定义

PAGE_BTR_SEG_TOP

10

B+树非叶子节点段的头部信息,仅在B+树的根页面中定义

File Header

多个页之间是通过双向链表相连的,这样也利于查找的时候向前和向后进行

名称

大小(字节)

描述

FIL_PAGE_SPACE_OR_CHKSUM

4

页面的校验和

FIL_PAGE_OFFSET

4

页号

FIL_PAGE_PREV

4

上一页的页号

FIL_PAGE_NEXT

4

下一页的页号

FIL_PAGE_LSN

8

页面被修改后的LSN值

FIL_PAGE_TYPE

2

该页的类型

FIL_PAGE_FILE_FLUSH_LSN

8

仅在表空间的第一个页中定义,代表文件至少被刷新到了对应的LSN值(在msyql崩溃恢复的时候就是读取这个LSN来进行redolog的恢复)

FIL_PAGE_ARCH_LOG_NO_OR_SPACEID

4

该页属于哪个表空间

其他页的类型:

名称

十六进制

描述

FIL_PAGE_TYPE_ALLOCATED

0x0000

最新分配,还未使用

FIL_PAGE_UNDO_LOG

0x0002

undo日志页

FIL_PAGE_INODE

0x0003

存储段的信息

FIL_PAGE_IBUF_FREE_LIST

0x0004

change buffer空闲列表

FIL_PAGE_IBUF_BITMAP

0x0005

change buffer的一些属性

FIL_PAGE_TYPE_SYS

0x0006

存储一些系统数据

FIL_PAGE_TYPE_TRX_SYS

0x0007

事务系统数据

FIL_PAGE_TYPE_FSP_HDR

0x0008

表空间头部信息

FIL_PAGE_TYPE_XDES

0x0009

存储区的一些信息

FIL_PAGE_TYPE_BLOB

0x0000A

溢出页

FIL_PAGE_INDEX

0x45BF

索引页(数据页)

File Tailer

8个字节组成,前4个字节代表页的校验和,每一次的页的信息被刷新到磁盘之前,都会被页的校验和算出来写入到file header的check sum中,完成之后会再写入到file tailer的check sum字段,二者一致代表刷新成功,反正刷新期发生了错误
后4个字节代表代表修改后的LSN,正常情况下应该和header中的FIL_PAGE_LSN相同。这两个字段都是为了校验页面的完整性。