Mysql的页结构(InnoDB)

在讲页结构之前,先说一下InnoDB的整体结构:
在这里插入图片描述
(主要是为了让小伙伴知道说的是在哪一层。。)
简单说就是 表空间是InnoDB存储引擎逻辑结构的最高层,表里面有段,段里面有区,区里面有页,页里面有行,行有具体的行格式。当然页也有自己的结构,这里主要讲的就是页结构。

在InnoDB中,管理存储空间的基本单位是页,一个页大小一般是16KB。平时我们将记录insert,InnoDB其实是将这个记录存放在页中的,InnoDB中,常见的页类型有:

  1. 数据页(B-tree Node)
  2. undo页 (undo Log Page)
  3. 系统页(System Page)
  4. 事务数据页(Transaction system Page)
  5. 插入缓冲位图页(Insert Buffer Bitmap)
  6. 插入缓冲空闲列表页(Insert Buffer Free List)
  7. 未压缩的二进制大对象页(Uncompressed BLOB Page)
  8. 压缩的二进制大对象页(compressed BLOB Page)

这里主要讲的是InnoDB的数据页的结构:

File header文件头部38字节页的一些通用信息
Page Header页面头部56字节数据页专用的一些信息
infimun + Supremum Records最小记录和最大记录26字节两个虚拟的行记录
User Records用户记录不确定实际存储的行记录内容
Free Space空闲空间不确定页中尚未使用的空间
Page Directory页面目录不确定页中的某些记录的相对位置
File Trailer文件尾部8字节检验页是否完整

一页的大小一般是16KB换成字节也就是 16384个字节,也就是说,UserRecords+FreeSpace+PageDirectory = 16384-38-56-26-8=16256字节

  • Infimun+Supremum
    从mysql的ibd文件中查看这两个属性,不知道自己的mysql的ibd文件在哪的小伙伴可以mysql中执行一下这行命令
show VARIABLES like 'datadir';

在这里插入图片描述
然后去对应的路径里面找就是了,每个表都会有一个ibd文件。
下面我们在这个文件里面找一下这两个属性。
在这里插入图片描述
这两个属性都是都是由5个字节的头信息 和 8个字节表示单词的信息构成
这里列出来一下这两个属性的最后8个字节:
infimum
在这里插入图片描述
最后一个00补位作用
supremum
在这里插入图片描述
在讲解前面5个字节的头信息之前,必须头信息的结构,这里的头结构和另一篇博客的记录头信息结构是一样的,这里先贴出来头信息的结构:

名称大小(单位:bit)描述
预留位11没有使用
预留位21没有使用
delete_mask1标记该记录是否被删除
min_rec_mask1B+树的每层非叶子节点中的最小记录都会添加该表记
n_owned4表示当前记录拥有的记录数
heap_no13表示当前记录在记录堆的位置信息
record_type3表示当前记录的类型,0表示普通记录,1表示B+树非叶子节点记录,2表示最小记录,3表示最大记录
next_record16表示下一条记录的相对位置

一共占用40big,也就是5个字节

这里再列出来一下这两个属性的前5个字节的信息:
Infimum
在这里插入图片描述
逐个讲解一下 00 02 01 1d 69 注意啊,这里的是16进制,1个16进制需要4个2进制位表示,这里一共10个16进制,那么换成2进制需要40个2进制位表示,和之前说的5个字节,5*8=40个2进制位也是能对应上的。

00换成2进制
0000 0000

02换成2进制
0000 0010

01换成2进制
0000 0001

1d换成2进制
0001 1101

69换成2进制
0110 1001

连在一起,也就是
0000 0000 0000 0010 0000 0001 0001 1101 0110 1001

对照着上面的头信息表结构简单解读一下:

000000000000 0010 0000 00010001 1101 0110 1001
预留1预留2delete_maskmin_rec_maskn_ownedheap_norecord_typenext_record
  • delete_mask:表示这条记录是否被删除,1删除 0没被删除。
  • min_rec_mask:B+树的每层非叶子节点中的最小记录都会添加该表记。
  • n_owned:表示当前记录拥有的记录数。
  • UserRecords + FreeSpace。
  • heap_no:表示当前记录在记录堆的位置信息 。
  • record_type:表示当前记录的类型,0表示普通记录,1表示B+树非叶子节点记录,2表示最小记录,3表示最大记录。
  • next_record:表示下一条记录的相对位置。

这里看这里的这个信息:
delete_mask是0,表示这里的这个infimum属性的伪头部信息这个没有被删除
min_rec_mask是0,表示这不是非叶子节点中的最小记录
n_owned是0,表示在infimum分组里面记录数为条。
heap_no是64,表示Infimum伪记录在页内的行记录相对位置为64.
record_type是1,表示这条伪记录是非叶子节点的记录,注意,这是是非叶子节点,但不是最小的记录。和上面的n_owned是0对应上,因为这条伪记录,是叶子节点,但不是最小的,所以和记录数n_owned等于0条记录对应上。
next_record是7529,表示当前记录(伪记录)到下一条真实记录的位置是7529个字节(根据这个来找表内的第一条数据),这里解释一下,下一条相距7529个字节,直接往后翻,就可以看到第一条数据。
这是我插入的数据。
在这里插入图片描述
这里可以在ibd文件中看到aaaa这个第一条数据
在这里插入图片描述


Supremum
字节信息:
03 000b 0000

000000110000 0000 0000 10110000 0000 0000 0000
预留1预留2delete_maskmin_rec_maskn_ownedheap_norecord_typenext_record

这里看这里的这个信息:
delete_mask是0,表示这里的这个Supremum属性的伪头部信息这个没有被删除
min_rec_mask是0,表示这不是非叶子节点中的最小记录
n_owned是3,表示在Supremum分组里面记录数为3条。
heap_no是1,表示Supremum伪记录在页内的行记录相对位置为1.
record_type是3,表示这个记录是最大的一条,和Supremum记录类型 的值一致,因为它本就是记录最大的一条数据的,并且这里的n_owned为3,里面存在3条。
next_record是0,表示当前记录的真实数据到下一条真实记录的位置是0.也就是没有下一条数据了。

  • UserRecords + FreeSpace
    当插入一个记录时,会根据我们指定的行格式,存储到User Records中,但是在一个页刚刚生成的时候,也就是里面一条数据都没有插入过的时候,UserRecords其实是不存在这个部分的。
    每次插入一个数据,就会从FreeSpace中分出一点空间给UserRecords,用作存储记录。当FreeSpace的空间被划分完了,也就是FreeSpace这个部分不存在了,也就表明这个页的空间用完了,如果还要插入,就要去获取新的页。

  • Page Directory
    记录在页中是按照主键的大小依次串联成一个单链表的,如果有主键,则按照主键的大小串联成单链表,没有主键有unique的字段,如果unique也没有,InnoDB会自己给你加一个隐藏的列,Row_id。如果我们要查找一个记录,遍历这个单链表可以找到结果,不过这个方法如果这个链表很长的话,就会很耗时,在InnoDB肯定不会这样去找,它是这样解决的:

  1. 将所有正常的记录(包括最小最大记录,但是不包括标记为已删除的记录)划分为几个组。
  2. 每个组的最后一条记录(也就是这个组里面最大的这条记录)的头信息的n_owned属性的值表示这个组里面拥有多少条记录。
  3. 将每个组的最后一条记录,也就是这个组的最大的记录单独提取出来,存储到靠近页的尾部的地方,这个地方就是Page Directory,和我们书本的最下面的页码一样。只不过这本书下面记录的不只是一个页码。这个东西称之为页目录。页目录里面存储的“页码”称为槽,实际生活中的书本的目录由很多页码组成,对应的,这里的页目录由很多槽组成。
    画图实在画不动了,这里借用一下别人的图,侵删,感谢!
    在这里插入图片描述
    这里就是槽的概念和PageDirect的直观图。
    看到这里,有没有发现这和B+树很像呢,这样设计也是为了提高查找效率,
    在一个页中,假设有100条数据.
    在这里插入图片描述
    这样就更像B+树了,要是还是看不出来,可以试着,横过来看看,看完回来,是不是发现了一颗B+树。
  • File Trailer
    这个部分主要是为了校验页的完成性。一共占了8个字节
    前4个字节:代表页的校验和。
    后4个字节:代表最后修改时对应的日志序列位置(LSN-Log Sequence Number)
    注意:后4个字节,只是用来记录LSN的位置,而不是具体的数值,可以通过
    在这里插入图片描述
    可以在mysql里面运行:show engine innodb status\G;里面可以看到LSN的具体值。

这里说最后一点东西,这是执行上面的命令得到的信息,贴在下面的是有关缓冲池的信息,和一点解释,后面一篇将会介绍缓冲池和行结构。
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 137363456
Dictionary memory allocated 391661
Buffer pool size   8192 #表示缓冲池一共  8192页,一页16k,即  8192 * 16kb   即之前查的  128M的缓冲池
Free buffers       7207 #表示当前Free列表中的页的数量
Database pages     980  #表示LRU列表中页的数量(Laster Recent Used)   7207 + 980 = 8187 != 8192  因为缓冲池中的页还要分配给自适应哈希索引、Lock信息、Insert Buffer等页,而这些页不需要使用LRU算法进行维护,因此不存在LRU列表中。
Old database pages 381
Modified db pages  0    #脏页的数量
Pending reads      0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 838, created 142, written 164
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 980, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值