字节二面你知道InnoDB行记录存储结构吗?

2021-08-19  本文已影响0人  Herman7z

程序员常用的IDEA插件:https://github.com/silently9527/Toolkit

前言

我们平时在向MySQL数据库表中插入数据时,实际数据是以行记录的格式存储在磁盘上的,本篇我们就一起来详细的了解下MySQL的行记录格式,理解了行记录的格式有助于我们后面了解MySQL如何快速在页中定位出行记录,以及MySQL的版本控制链,事务隔离级别等等,行记录格式是许多MySQL核心知识的基础。

InnoDB行记录类型

MySQL中总共提供了四种类型的行格式:Compact,Redundant,Dynamic,Compressed

在创建表或修改表的时候可以指定行记录的格式
create table 表名 row_format=行格式名
alter table 表名 row_format=行格式名

知道就行,不需要去记住,基本上使用不到

Compact行格式

在四种类型的行格式中,我们主要来学习Compact格式,其他格式的行记录类似;

image

从图中我们可以看出行记录主要是由4部分组成:变长字段长度、Null值列表,行记录头信息以及列的真实数据

变长字段长度列表

在MySQL中很一些变长的数据类型(varchar,text等),MySQL需要知道这些数据的实际长度,这样才能正确的在真实数据中取出对应列的数据,所以变长字段是由两部分组成:

每个变长字段的长度要么用1字节要么用2字节表示,由此就决定了每个字段的最大字节数是65535;

那到底什么时候选用1字节什么时候选用2字节呢?

这里需要定义三个变量:w,m,l

  1. 假如使用的字符集是utf8mb4,每个字符占用的字节数是4字节,那么w=4;假如字符类型若为utf8,每个字符最多占3个字节,那么w=3; 所以w表示字符集中每个字符所占的字节数
  2. varchr(m),这里m表示的是定义的字符的长度
  3. l 表示的是该字段真实数据占用的字节数

m*w <= 255;表示该字段定义的最大长度都不会超过1字节,那么该字段的长度就用1字节表示

m*w > 255 && l<=127; 表示该字段定义的长度可能会超过1个字节,但是当前的实际长度是小于127的,可以用1个字节表示

m*w > 255 && l>127; 用2字节来表示该字段的长度

思考:为什么与l比较的值是127呢?
当我们定义的变长字段可能大于255(也就是超过一个字节)时,MySQL如何才能知道当前读取的字节该字段的完成字段长度,还是该字段的半个字段长度,为了解决这个问题,MySQL使用了1字节的首位,当首位为0表示当前是1字节,当首位为0表示当前长度是2字节;由于占用了1字节的首位,所以剩下7位所能表示的最大值是127

变长字段不会存储为Null列的长度;其次并不是行记录中一定需要变长字段长度这段内容,如果行记录中没有定义变长字段或者是变长字段都为Null,那么就不会有变长字段长度这部分

变长字段占用的字节数按照顺序逆序存储

Null值列表

一条记录中某些列通常可能允许为null,所以Compact行格式把这些允许为null的进行了统一管理;

  1. 首先统计出表中定义的哪些列允许为null
  2. 如果表中的字段都不能为空,那么就不存在null值列表;如果存在允许为null的字段,那么就按照字段的顺序为每个字段对应一个二进制位,当二进制位为1时表示该列值为空;当二进制位位0时表示该列值不为空
  3. Null值列表必须有整数个字节来表示,所以对应没有占用的位使用0补位
image

行记录的头信息

头信息中主要包含了6个字段,其中5个字段也是在面试中经常被问到的,为了方便记忆,我们把5个字段对应到手的5根指头:

最后一个字段min_rec_flag : B+树中每层非叶子结点最小目录项记录该字段为1;该字段相对于其他5个字段显得不那么重要,不会影响理解B+树索引

隐藏列

除了用户自定义的数据列以外,MySQL还会为每行记录生成3个隐藏列

溢出列

MySQL中所有的行记录都会被存储在数据页中,每个数据页的大小是16KB,也就是16384个字节;在前面我们讲过变长字段的长度可以用两个字节来表示,所以列的最大长度可以是65535,当遇到这种极端情况时,一个数据页是存储不下这一条记录的。

Compact行格式针对这种情况的处理方式是在真实的数据处记录该列的一部分数据(768字节),其他多余的数据会存储到新的数据页中(溢出页),然后在该记录中使用20个字节存储这些数据页的地址

image

溢出页与溢出页之间使用的链表相连接

其他的行记录格式:

Redundant:MySQL5.0之前的格式,直接忽略

Dynamic,CompressedCompact很像,只是在溢出列的处理有些差异,他们只会在真实数据列中使用20个字节存储溢出页的地址

面试题

欢迎大家在评论区留言讨论


最后(点关注,不迷路)

文中或许会存在或多或少的不足、错误之处,有建议或者意见也非常欢迎大家在评论交流。

最后,写作不易,请不要白嫖我哟,希望朋友们可以点赞评论关注三连,因为这些就是我分享的全部动力来源🙏

image
上一篇 下一篇

猜你喜欢

热点阅读