InnoDB是存储引擎,负责将磁盘的数据按照我们的逻辑概念“表”那样存取,这里首先总结下表中每一行数据是以何种形式被InnoDB存储再磁盘的。InnoDB的行记录存储形式有很多种,compact、dynamic、redundant、compressed等。下面介绍compact格式的行数据结构:
每一行的数据组成
除了我们自己的真实数据外,为了提高性能和用于存取这行InnoDB需要加上必要的数据,这叫做额外信息。每一行数据都由额外信息 + 真实数据组成。 其中额外信息里又分为变长字段长度列表、null字段列表、记录头信息(记录头信息有很多用于存取行、管理行的数据);真实数据也并不是只有我们自己设置的数据,mysql还会为其添加一些字段例如:事务Id、回滚指针、行Id(没有设置主键时用于唯一标识行)。
额外信息的变长字段长度列表
如果某个字段设置为变长,mysql必须知道这个字段实际长度,不然mysql取这个字段时根本不知道取多少。变长字段的长度就存放在额外信息的变长字段长度列表里,但是不是顺序的而是倒序的。当然,如果这一行没有变长字段,这一个列表就不存在。例如:表中有如下数据:
a(varchar(255)) | b (varchar(256)) | c(varchar(256)) --------------------------------------------------------------------- sq | s.....(128个s) | s //第1行
第一行有三个变长字段,长度分别是 2B、128B、1B(我们假设字符集是ascii,一个字母一字节)。那么在变长字段长度列表里应该是:| 1 128 2 |,这几个数字占有内存的情况是:最大长度小于256,分配一字节;最大允许长度大于255且实际占用小于128,也分配一字节;最大允许长度大于255,且实际长度大于127则分配两字节。所以长度列表的内存分配应该是 1B + 2B +1B,共4B。
(由于记录变长字段实际大小的数字分配最躲2B空间,所以最多只能表示到65535,即每列最大65535B。)
额外信息的null值列表
如果某几个列允许为null,那么为null值时不会记录在真实数据而是记录在额外信息里。和变长字段长度列表一样,也是倒序记录,采用bit记录。例如null值列表:0000 1001 ,表示第1个和第4个字段为null值。如果一行没有可以为null的字段,这个就不存在。
值的注意的是:这个列表的内存单位是字节为单位。例如有7个可为null的字段,就需要分配1B记录;如果有9个字段可为null,就需要2B(因为需要9个bit了)。
额外信息的记录头信息
这里有mysql操作记录所必须的数据,主要有:heap_no表示当前记录在记录堆的位置信息,next_record表示下一条记录的相对位置。等等。
真实数据的隐藏列
隐藏列不是我们加上去的数据,是mysql加上去并维护的,但是也属于是真实数据。例如有:DB_ROW_ID,行id唯一标识一条记录;DB_TRX_ID事务id;DB_ROLL_PTR回滚指针等等。
(InnoDB一页16KB,而MySQL限制不算BLOB、TEXT列每行大小不超过65535B,因此有可能出现一页装不下一行数据的i情况。compact处理这种情况就是能放进的数据照常存放,然后用这一页的最后20B记录剩下的数据存放在哪些页哪些位置,相当于地址加偏移)
MySQL8中InnoDB的默认行格式是Dynamic,它与compact类似,只是在行溢出的时候有一点不同,只要这一行数据大小超过16KB,就直接用20B记录存放数据的页和位置,想当于这行的真实数据一点也不留点放在当前页。
来源:https://www.cnblogs.com/shen-qian/p/12607385.html