MySQL-InnoDB数据页结构

55 阅读5分钟

跟孙哥学java

孙哥主页

数据页代表这块16KB大小的数据结构可以划分成多个部分,不同部分代表不同的功能。

记录在页中的存储

我们把我们的行数据存到User Records 这个部分。当这一页没有数据的时候,User Records这个部分的大小为0,当我们要插入一行数据的时候,会去向Free Space中申请空间,划分给User Records,当 Free Space的空间全部被User Records给替代时候,这个页就存满了,如果话有数据要插入的话,就要去申请新的页了。 过程如下

记录头信息

先创建一个表,并且插入数据

mysql> create table page_demo(
    -> c1 int,
    -> c2 int,
    -> c3 varchar(10000),
    -> primary key(c1)
    -> ) charset=ascii row_format=Compact;

mysql> INSERT INTO page_demo VALUES(1, 100,
    -> 'aaaa'), (2, 200, 'bbbb'), (3, 300, 'cccc'), (4,
    -> 400, 'dddd');
    

这个表的行格式如下图: image.png image.png

每条记录都有一个记录头信息: 其中delete_mask 标记当前记录是否被删除:如果删除就是1,未删除就是0.为什么需要这个记录呢?因为直接删除会让数据页中的数据重新排序,而重新排序又会造成性能的消耗。所以就采用标志位的方式来记录该记录是否被删除。 min_rec_mas: B+树中,每层非叶子节点都会加入这个标记,0表示叶子节点。 n_owned: 表示在一个糟中,存储的记录个数 heap_no: 表示当前记录在页中的位置。比如上面我们插入的四条数据中在页中的位置分别是2,3,4,5。因为我们的主键是按顺序,1,2,3,4插入的,所以是这个顺序。 为什么是2,3,4,5 因为在页中存在 存在 Infimum+Supremum的部分。 这个分别是页中的最小记录数,和最大记录数。 因此最小记录数和最大记录数在页中的位置是0和1 image.png

record_type: 这个表示当前记录的类型:⼀共有4种类型的记录,0表示 普通记录,1表示B+树⾮叶节点记录,2表示最⼩记录,3表示 最⼤记录。从图中我们也可以看出来,我们⾃⼰插⼊的记录就 是普通记录,它们的record_type值都是0,⽽最⼩记录和最 ⼤记录的record_type值分别为2和3。

next_record: 指向下一条记录的next_record。这个指向不是我们插入的顺序的下一条 而是按主键顺序的下一条记录 Infimum记录(也就是最⼩记录) 的下⼀条记录就本⻚中主 键值最⼩的⽤户记录,⽽本⻚中主键值最⼤的⽤户记录的下⼀ 条记录就是 Supremum记录(也就是最⼤记录)

页目录 Page Directory

现在我们了解了页中的记录都是按照主键顺序-->形成的一个单链表 如果我们要去查询,怎么查呢? 比如查询一个 c1=3的数据? 难道从infimum开始遍历整个链表吗? 这样查询的效率是O(N) 数据量小的时候查起来还好,数据量大了就很耗费性能了

所以InnoDB讲页中的记录分成了多个组。 每个组对应一个插槽,会在Page Header中记录每个插槽中最大记录的next_record的地址 通过2分查找对应数据在的插槽 再在插槽中进行遍历查找我们要找的数据, 因为一个插槽 中的数据为1-8个,所以这个遍历很快

Page Header(页面头部)

因为要根据插槽去查找数据: 页头部的信息有: Page_N_DIR_SLOTS 记录页中插槽的数量 PAGE_HEAP_TOP 记录未使用空间的最小地址---> 也就是从该地址开始就是Free Space PAGE_N_HEAP 本页中记录的数量(包括最大和最小记录) PAGE_FREE 第一个被删除的记录,所有被删除的记录也会组成一个单链表,方便重复利用 PAGE_DIRECTION 记录插入的方向 ,比如上一条插入的主键为1,这一条插入的主键为2,这个方向就是→ PAGE_N_DIRECTION 假设连续⼏次插⼊新记录的⽅向都是⼀致的,InnoDB会把沿 着同⼀个⽅向插⼊记录的条数记下来,这个条数就 ⽤PAGE_N_DIRECTION这个状态表示。当然,如果最后⼀条 记录的插⼊⽅向改变了的话,这个状态的值会被清零重新统 计

File Header (文件头部)

File Header针对各种类型的⻚都通⽤,也就是说不同类型的⻚都 会以File Header作为第⼀个组成部分,它描述了⼀些针对各种⻚ 都通⽤的⼀些信息,⽐⽅说这个⻚的编号是多少,它的上⼀个⻚、下 ⼀个⻚是谁

FIL_PAGE_SPACE_OR_CHKSUM ⻚的校验和 (checksum值) FIL_PAGE_OFFSET 4字 节 ⻚号 FIL_PAGE_PREV 4字 节 上⼀个⻚的⻚号 FIL_PAGE_NEXT 4字 节 下⼀个⻚的⻚号 FIL_PAGE_LSN 8字 节 ⻚⾯被最后修改时 置 对 ( 应 英 的 ⽂ ⽇ 名 志 是 序 : 列 L 位 og Sequence Number) FIL_PAGE_TYPE 2字 节 该⻚的类型FIL_PAGE_FILE_FLUSH_LSN 8字 节 仅在系统表空间的 ⼀个⻚中定义,代 表⽂件⾄少被刷新 到了对应的LSN值 FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID 4 节 字 ⻚属于哪个表空间