mysql数据页结构

数据页结构

mysql默认每个数据页为16KB,InnoDB引擎的Compact行记录结构由以下字段组成:

变长字段长度列表 null值列表 记录头信息 列数据1 列数据N
不定长 不定长 5字节

变长字段长度列表

对于非固定长度的字段类型,例如varchartextblob、多字节编码的char等,通过变长字段长度列表记录当前行记录的对应字段值的长度(列顺序倒序存放)。

列名 值长度(10进制) 值长度(16进制)
a 'aaa' 3 0x03
b 'b' 1 0x01
c 'ccccc' 5 0x05

则示例的变长字段长度列表的值为05 01 03

null值列表

如果记录的列允许为null,则在该值中记录当前行中值为null的字段(列顺序倒序存放)。

列名 允许为null 是否为null 值(2进制)
a true true 1
b false - -
c true true 1
d true false 0

则示例的null值列表的值为011(二进制),又由于该值必须为整数字节,所以高位补0后的值为000000110x03。如果表中允许为null的列超过8个,则null值列表的值长度大于1字节。

记录头信息

记录头占固定长度5字节:

名称 大小(bit) 描述
() 1 未知
() 1 未知
deleted_flag 1 该行是否已被删除
min_rec_flag 1 为1,如果该记录是预先定义为最小的记录
n_owned 4 该记录拥有的记录数
heap_no 13 索引堆中该条记录的排序记录
record_tye 3 记录类型,000表示普通,001表示B+树节点指针,010表示Infimum,011表示Supremum,1xx表示保留
next_record 16 页中下一条记录的相对位置

案例

CREATE TABLE `user_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(11) NOT NULL,
  `age` int(11) DEFAULT NULL,
  `address` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

insert into user_info (id,name,age,address) values (1,'tom',18,'shanghai');

查看mysq目录下的文件user_info.ibd,通过命令hexdump -Cv user_info.ibd > user_info.txt或者使用软件例如UltraEdit查看二进制数据。

普通记录

0x0000C078位置

在这里插入图片描述

08                      变长字段address的长度为8
03                      变长字段name的长度为3
00                      null值字段列表
00 00 10 FF F0          记录头信息(5字节)
80 00 00 01             RowID:主键id的值为1
00 00 00 1D 4B 93       事务ID(6字节)
E7 00 00 80 31 01 10    回滚指针(7字节)
74 6F 6D                字段name的值:tom
80 00 00 12             字段age的值:18
73 68 61 6E 67 68 61 69 字段address的值:shanghai

最大/最小记录

数据页的每行数据以单向链表的形式连接,因此需要有链表头和链表尾。最小记录就是该单向链表的链表头,最大记录则是该单向记录的链表尾,且两者的记录位置固定不变。

最小记录的位置为0x0000C063,其值固定为infimum

在这里插入图片描述

01 00 02 00 1D          记录头信息(5字节)
69 6E 66 69 6D 75 6D    最小记录(固定值infimum)

最大记录的位置为0x0000C070,其值固定为supremum

在这里插入图片描述

02 00 0B 00 00          记录头信息(5字节)
73 75 70 72 65 6D 75 6D 最大记录(固定值supremum)

Page Directory

Page Directory中存放了当前数据页中部分数据的相对位置,即
Page Directory是当前数据页数据的目录,mysql通过Page Directory使用二分法减少查询时间。

Page Directory中每个相对位置占2个字节长度,且相对位置从0x0000FFF7倒序排序。其中至少有最小记录和最大记录的相对位置,如下图:

00 63 表示 0x0000C06300 70 表示 0x0000C070

在这里插入图片描述

当表行数据较多时(创建了35行数据),Page Directory会每4~8条记录存一个相对位置,例如下图:

在这里插入图片描述

00 63 -> 0x0000C063 -> 最小记录

00 F8 -> 0x0000C0F8 -> ID为4的记录

01 98 -> 0x0000C198 -> ID为8的记录

02 38 -> 0x0000C238 -> ID为12的记录

02 D8 -> 0x0000C2D8 -> ID为16的记录

03 78 -> 0x0000C378 -> ID为20的记录

04 18 -> 0x0000C418 -> ID为24的记录

04 B8 -> 0x0000C4B8 -> ID为28的记录

00 70 -> 0x0000C070 -> 最大记录

数据链表

数据页中行记录按照主键值由小到大顺序串联成一个单链表,且单链表的链表头为最小记录,链表尾为最大记录。并且为了更快速地定位到指定的行记录,通过Page Directory实现目录的功能,借助Page Directory使用二分法快速找到需要查找的行记录。

在这里插入图片描述

删除表(为了清空文件防止删除的记录干扰)后重新创建表和数据:

CREATE TABLE `user_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(11) NOT NULL,
  `age` int(11) DEFAULT NULL,
  `address` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

insert into user_info (id,name,age,address) values (3,'tom',18,'shanghai');
insert into user_info (id,name,age,address) values (1,'peter',22,null);
insert into user_info (id,name,age,address) values (2,'wsen',21,'beijing');

在这里插入图片描述

最小记录:

01 00 02 00 44
69 6E 66 69 6D 75 6D    最小记录(固定值infimum)

最大记录:

04 00 0B 00 00
73 75 70 72 65 6D 75 6D 最大记录(固定值supremum)

ID为3的记录:

08                      变长字段address的长度为8
03                      变长字段name的长度为3
00                      null值字段列表
00 00 10 FF F0          记录头信息(5字节)
80 00 00 03             RowID:主键id的值为3
00 00 00 1D 4B 80
DB 00 00 80 2E 01 10
74 6F 6D                字段name的值:tom
80 00 00 12             字段age的值:18
73 68 61 6E 67 68 61 69 字段address的值:shanghai

ID为1的记录:

05                      变长字段name的长度为5
02                      null值字段列表:0x02 -> 00000010即address为null
00 00 18 00 22          记录头信息(5字节)
80 00 00 01             RowID:主键id的值为1
00 00 00 1D 4B 81
DC 00 00 80 1B 01 10
70 65 74 65 72          字段name的值:peter
80 00 00 16             字段age的值:22
                        字段address的值:null

ID为2的记录:

07                      变长字段address的长度为7
04                      变长字段name的长度为4
00                      null值字段列表
00 00 20 FF B7          记录头信息(5字节)
80 00 00 02             RowID:主键id的值为2
00 00 00 1D 4B 86
DF 00 00 80 2F 01 10
77 73 65 6E             字段name的值:wsen
80 00 00 15             字段age的值:21
62 65 69 6A 69 6E 67    字段address的值:beijing

Page Directory

在这里插入图片描述

最小记录的记录头信息最后2字节00 44 -> 0x0000C063偏移0x0044 -> 0x0000C0A7,即ID为1的记录的id位置;

ID为1的记录的记录头信息最后2字节00 22 -> 0x0000C0A7偏移0x0022 -> 0x0000C0C9,即ID为2的记录的id位置;

ID为2的记录的记录头信息最后2字节FF B7 -> 0x0000C0C9偏移0xFFB7 -> 0x0000C080,即ID为3的记录的id位置;

ID为3的记录的记录头信息最后2字节FF F0 -> 0x0000C080偏移0xFFF0 -> 0x0000C070,即最大记录的记录位置;

发布了185 篇原创文章 · 获赞 38 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/sz85850597/article/details/94406677