主要包含了对页面之间双向链表的表示、页面校验和、页面最后被修改对应的日志序列位置
用户记录:
? 用户记录中的记录按照指定的行格式一条条摆在该区域,相互之间形成单链表。
页目录:
1、页目录分组的个数如何确定?
由InnoDB规定:最小记录所在的分组只能有一条记录,最大记录所在分组的记录条数只能在18之间,剩下的分组中记录的条数在48之间。
2、页目录结构下如何快速查找记录?
1、通过二分法确定该记录所在的槽,并记录该槽所在分组中主键值最小的那条记录。
2、通过记录的next_record属性遍历该槽所在组中的所有记录。
页面头部:
记录了页目录和页面的相关信息
CREATE TABLE 表名 ROW_FORMAT=行格式
ALTER TABLE 表名 ROW_FORMAT=行格式
为什么定义NULL值列表?
? 定义NULL值列表是因为数据是需要对齐的,如果没有标注出NULL值的位置,在查询数据的时候有可能会出现混乱,记录的格式为:
? 在这个过程中会 跳过主键,因为主键不为空。
字段 | 大小(bit) | 描述 |
---|---|---|
delete_mask | 1 | 该记录是否被删除 |
min_rec_mask | 1 | B+树每层非叶子节点的最小节点 |
record_type | 4 | 当前记录类型,0表示普通记录,1表示B+树非叶子节点记录,2表示最小记录,3表示最大记录 |
heap_no | 13 | 当前记录在记录堆的位置信息 |
n_owned | 3 | 当前记录拥有的记录数 |
next_record | 16 | 下一条记录的相对位置,指向下一条记录的逻辑位置 |
问题:
1、使用delete_mask标记当前记录是否被删除,被删除的记录为什么还在页中存储呢?
? 这些被删除的记录之所以不立即从磁盘上移除,是因为移除它们之后其他记录在磁盘上需要重新排列,导致性能消耗。通过将所有打上删除标记的记录组成垃圾链表
,之后如果有新纪录插入到表中来时,可以把这些被删除的记录占用的存储空间覆盖掉。
2、heap_no为什么是从2开始的?
? MySQL自动给每个页里加了两个虚拟记录,一个代表最小记录名,heap_no值为0;一个代表最大记录,heap_no值为1。
? Dynamic和Compressed将实际数据存放在溢出页中,Compressed行记录格式会将存储在其中的行数据以zlib的算法进行压缩。
行溢出
? 一个页的大小为16KB,也就是16384字节,而VARCHAR类型的列最多可以存储65535个字节,这样可能会出现一页存放不下一条记录的情况。这就是行溢出。