一、页结构说明

大致分7部分

二、记录在页中的存储
2.1 页面记录内存结构
行格式 存储到 User Records 部分,每当我们插入一条记录,都会从 Free Space 部分申请一个记录大小的空间划分到 User Records 部分 ,用完则申请新的页;
User Records记录行数据-> Free Space 空间->用完则申请下一页面
mysql> CREATE TABLE page_demo(
-> c1 INT,
-> c2 INT,
-> c3 VARCHAR(10000),
-> PRIMARY KEY (c1) -> )
CHARSET=ascii ROW_FORMAT=Compact; Query OK, 0 rows affected (0.03 sec)
行格式,头信息

mysql> INSERT INTO page_demo VALUES
(1, 100, 'aaaa'), (2, 200, 'bbbb'), (3, 300, 'cccc'), (4, 400, 'dddd');
Query OK, 4 rows affected (0.00 sec) Records: 4 Duplicates: 0 Warnings: 0
数据存储行信息示意图:

1、delete_mask:1个二进制位,值为 0 的时候代表记录并没有被删除,为 1 的时 候代表记录被删除掉了;数据分两步加入垃圾链表???
2、min_rec_mask B+树的每层非叶子节点中的最小记录都会添加该标记。
3、heap_no 当前记录在本页 中的位置;0,1是mysql默认的两个伪记录,代表最小值和最大值。
不存放在 页 的 User Records 部分,他们被单独放在 一个称为 Infimum + Supremum 的部分;
****按****照主键从小到大的顺序形成了一个单链表*****
2.2 删除数据链表变化

1、第2条记录并没有从存储空间中移除,而是把该条记录的 delete_mask 值设置为 1 。
2、第2条记录的 next_record 值变为了0,意味着该记录没有下一条记录了。
3、第1条记录的 next_record 指向了第3条记录。
4、还有一点你可能忽略了,就是 最大记录 的 n_owned 值从 5 变成了 4。
不论增删改操作,InnoDB始终会维护一条记录的单链表,链表中的各个节点是按照主键值由小到大的顺序连接起来的。
第二条存储空间却没有回收,再次把这 条记录插入到表中,会发生什么事呢?
mysql> INSERT INTO page_demo VALUES(2, 200, 'bbbb');
InnoDB 并没有因为新记录的插入而为它申请新的存储空间,而是直接复用了原来被删除记录 的存储空间;(重用垃圾链表的存储空间)
三、Page Directory(页目录)
3.1 页目录结构
对于最小记录所在的分组只能有 1 条记录, 最大记录所在的分组拥有的记录条数只能在 1~8 条之间,剩下的分组中记录的条数范围只能在是 4~8 条之间。

页中数据查找过程:
-
通过二分法确定该记录所在的槽,并找到该槽中主键值最小的那条记录。
-
通过记录的 next_record 属性遍历该槽所在的组中的各个记录。
3.2 Page Header(页面头部)

PAGE_DIRECTION 和 PAGE_N_DIRECTION 的意思:
PAGE_DIRECTION
假如新插入的一条记录的主键值比上一条记录的主键值大,我们说这条记录的插入方向是右边,反之则是左边。用来表示最后一条记录插入方向的状态就是 PAGE_DIRECTION 。
PAGE_N_DIRECTION
假设连续几次插入新记录的方向都是一致的, InnoDB 会把沿着同一个方向插入记录的条数记下来,这个条数就用 PAGE_N_DIRECTION 这个状态表示。当然,如果最后一条记录的插入方向改变了的话,这个状态的值会被清零重新统计。
3.3 File Header(文件头部)

数据页结构: 形成双向链表
1、FIL_PAGE_OFFSET:页号(不连续)。
2、FIL_PAGE_PREV和FIL_PAGE_NEXT:本页的上一个和下一个页的页号。

3.4 File Trailer:校验页数据是否完整

3.5 总结
1、InnoDB为了不同的目的而设计了不同类型的页,我们把用于存放记录的页叫做 数据页 。
2、一个数据页可以被大致划分为7个部分,分别是
File Header ,表示页的一些通用信息,占固定的38字节。
Page Header ,表示数据页专有的一些信息,占固定的56个字节。
Infimum + Supremum ,两个虚拟伪记录,表示页中的最小和最大记录,占固定的 26 个字节。
User Records:真实存储我们插入的记录的部分,大小不固定。
Free Space :页中尚未使用的部分,大小不确定。
Page Directory:页中的某些记录相对位置,也就是各个槽在页面中的地址偏移量,大小不固定,插入的记录越多,这个部分占用的空间越多。
File Trailer:用于检验页是否完整的部分,占用固定的8个字节。
3、每个记录的头信息中都有一个 next_record 属性,从而使页中的所有记录串联成一个单链表 。
- InnoDB会为把页中的记录划分为若干个组,每个组的最后一个记录的地址偏移量作为一个槽 ,存放在 Page Directory中,所以在一个页中根据主键查找记录是非常快的,分为两步:
通过二分法确定该记录所在的槽。
通过记录的next_record属性遍历该槽所在的组中的各个记录。
5、每个数据页的File Header部分都有上一个和下一个页的编号,所以所有的数据页会组成一个双链表。
6、为保证从内存中同步到磁盘的页的完整性,在页的首部和尾部都会存储页中数据的校验和和页面最后修改时对应的 LSN 值,如果首部和尾部的校验和和LSN值校验不成功的话,就说明同步过程出现了问题。