1 页结构总览
2 建表语句
create table page_demo(
c1 int,
c2 int,
c3 varchar(100),
primary key(c1)
)charset=ascii row_format=COMPACT;
3 User Records & Free Space
插入一条记录时,都会从Free Space中申请一个记录的大小,划分到User Records部分。当Free Space中所有的空间全部被User Records部分替代之后,这个也就用完了。
3.1 重新看看行格式
先往表中插入几条数据
insert into page_demo values(
(1, 100, 'aaaa'),
(2, 200, 'bbbb'),
(3, 300, 'cccc'),
(4, 400, 'dddd')
)
所有的记录都比Infimun
记录大,所有的记录都比Spuremum
记录小.
4 Infimum
& Spuremum
4.1 删除一条记录
Delete from page_demo where c2 = 2
4.2 重新插入记录
insert into page_demo values(
(2, 200, 'bbbb'),
)
链表就恢复原样了.
5 Page Directory
如果现在要开始查询一条记录:
select * from page_demo where c1 = 3;
需要从Infimun
开始往后遍历单链表,时间复杂度O(N),所以需要一种办法来加速查询。
- 所有正常记录(包括
Infimun
和Spuremum
,不包括垃圾链表中的记录)划分为几个组 - 每个组的最后一条记录都是这个组的负责人,负责人知道这个组中有几条记录(也就是 n_owned,包括负责人自己在被内)
- 把每个组的最后一条记录在页中的偏移量记录到页的末尾部分,
末尾部分这个额外的记录就是页目录,页目录中每个元素都是两个字节,这两个字节是一个 目录槽位.
有了页目录之后就可以使用二分查找了。
6 Page Header
插入方向:假如新插入的记录主键值比上一条记录的主键值大,这条记录的插入方向就是右边,反之就是向左的
此方向插入的条数:一旦方向改变,立马开始重新计数
7 File Header
-
Check Sum:本页面的校验和
-
File Page Offset:页号
-
Page Type:
-
Undo 日志页
-
溢出页
-
索引页(就是我们的数据页)
-
Change Buffer空闲列表
-
…
-
-
双向链表指针,把每个页穿成双向链表
-
LSN
页面最后被修改的时候的LSN
号
8 File Trailer
-
页校验和:
与File Header中的校验和相对应,内存中的页修改之后,在刷盘前需要先算出这个页面的校验和,校验和数字先写入File Header,然后开始写磁盘,完全写完之后,需要把校验和写入File Trailer中的位置。
如果写过程中发生了断电,重启之后把数据载入内存会检测到两个位置的校验和不一致,就意味着刷新期间发生了错误。
-
LSN
号的后四个字节,正常情况也要与File Header中的LSN
相同