InnoDB数据页结构(3)之记录头信息分析

InnoDB数据页结构之记录头信息分析

在之前的文章中有分析得到记录头每个部分的二进制值如下所示

对应表数据如下所示

+----+------+------+
| c1 | c2   | c3   |
+----+------+------+
|  1 |  100 | aaaa |
|  2 |  200 | bbbb |
|  3 |  300 | cccc |
|  4 |  400 | dddd |
+----+------+------+

下面来具体分析下这些值的具体含义(当然不包含预留位1和预留位2)

delete_mask

delete_mask是一个删除标识当该值为0时表示正常数据,为1时表示已删除数据,可以做如下实验

删除c1=1的列,也就是第一列

mysql> delete from page_demo where c1=1;
Query OK, 1 row affected (0.01 sec)
-- 再次查询,只剩三列
mysql> select * from page_demo;
+----+------+------+
| c1 | c2   | c3   |
+----+------+------+
|  2 |  200 | bbbb |
|  3 |  300 | cccc |
|  4 |  400 | dddd |
+----+------+------+
3 rows in set (0.00 sec)

同时再次获取page_demo的ibd文件,同时通过hexdump转换为16进制信息如下所示

其中被删除的记录头信息如下所示

十六进制:20 00 10 00 00
二进制 :00100000 00000000 00010000 00000000 00000000

到这里我们可以对比得出,当我们执行delete语句删除数据时,其实仅仅是将该条记录的记录头信息中的delete_mask由0改为了1相当于打了一个删除标识,并没有立即在磁盘中将该条数据删除,因为移除这些空间还需要将空间重新整理消耗性能,这些已经删除的记录会形成一个垃圾链表,这个链表占用的空间被称为可重用空间。

min_rec_mask

这里先简单理解为B+树的每层非叶子节点中的最小记录将会采用该字段标记。

heap_no

这个属性表示这条记录在该页中的位置,从上图列表中可以看到表中对应的四条数据heap_no的值依次为2、3、4、5这时就有疑问了,为什么是从2开头呢?难道前面还有隐藏记录?这就要聊到最小记录infimum和最大记录supremum被称为伪记录或者虚拟记录,这两条记录十分简单就是由5个字节的记录头以及8个字节的固定部分构成如下所示

根据page_demo的ibd文件,如下所示

....省略记录
0000c050  00 02 00 f2 00 00 00 68  00 00 00 02 00 32 01 00  |.......h.....2..|
0000c060  02 00 1c 69 6e 66 69 6d  75 6d 00 05 00 0b 00 00  |...infimum......|
0000c070  73 75 70 72 65 6d 75 6d  04 00 00 00 10 00 20 80  |supremum...... .|
....省略记录

可得到infimum和supremum的记录头信息

infimum :01 00 02 00 1c
supremum:05 00 0b 00 00

将上面十六进制数据转为二进制如下

infimum :00000001 00000000 00000002 00000000 00011100
supremum:00000005 00000000 00001011 00000000 00000000

那么最小记录和最大记录的记录头信息拆分如下

从这里就可以看出最小记录和最大记录的为每个页0和1的位置,业务数据从2开始。

record_type

从上面测试表page_demo的测试列记录头信息和伪记录(最小记录和最大记录)可以看出record_type有三种值0、2、3不过从这三个值也很容易推理出还有一个类型值为1,分别代表什么意思呢?

  • 0:业务数据,普通记录。

  • 1:B+树的非叶子节点(本文暂时还没用到)。

  • 2:最小记录。

  • 3:最大记录。

next_record

当前记录的真实数据到下一条记录的真实数据的地址偏移量,这里就可以简单理解为链表,不过需要注意的是这个链表的顺序并不是指插入顺序,而是根据表的主键由小到大排列,这里也包含最小记录和最大记录,如下所示

无论数据如何操作数据页都会维护一个单链表,当有数据删除时,该条数据的next_record将会置为0表示没有下一条记录了。

n_owned

我们知道所有的记录由next_record连接起来形成一个链表后,思考一个问题,链表的痛点是什么?无非是查找效率低,那么InnoDB为什么还要使用链表呢?显然是对链表做了优化的,为了高效查找InnoDB将包括最小记录infimum和最大记录supremum在内的正常记录分组(不包含已删除记录),而每个组最大的那条记录的n_owned字段则表示每个组的记录数量,所以测试表中包含了两个组

  • 第一组:最小记录infimum所在记录,只有自身一条记录。

  • 第二组:最大记录supremum所在记录,自身一条记录和四条业务记录所以n_owned才为5。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值