mysql学习笔记2

57 阅读5分钟

行记录的存储

行记录的结构

在mysql中我们添加的数据最后都会以行数据的形式存储到磁盘中。

mysql提供了多种行格式来使用,下面先介绍最常用的COMPACT行格式。

image.png

从结构图同可以看到,行数据分成了两部分:额外信息和真实数据两部分,真实数据很好理解,就是我们实际存储的信息,额外信息的作用将在下面详细说明一下。

1、变长字段长度列表

该列表是用来记录mysql中变长字段的实际长度的。在mysql中,比如varchar、Text等格式的长度是不固定的,如果直接将这些值存储到磁盘中不加标记,那么mysql将无法判断实际数据中这个字节是那个列的内容。所以将变长字段的长度和其实际内容分开存储。

在存储上变成字段长度列表中存储的字段长度顺序和我们设置的长度顺序是相反的,即列顺序的逆序,也就是说,我们在设置列的时候顺序是ABC,在变长列表中存储的顺序就变成了CBA。因为mysql中每行的行数据的连接是通过上图中的记录头中记录的偏移量来跳转的,通过这样跳转会跳到下一行数据的额外信息和真实数据中间的位置上。那么这样向两边读数据可以尽可能地将信息匹配对应上,提升缓存利用率,减少缓存切换的情况。

字段长度的不同在列表上会使用不同长度的字节来记录,一个字节有8位比特,所以算上0可以存储0到255位数字。因此,长度在255及以下的都会使用1个字节来记录长度。其具体的设计规则如下:

  1. 字符所使用的最大字节数 乘以 变长长度的最大值(以字符为单位) 小于255 ,就用1个字节来记录。
  2. 如果上述结果大于255,就会进行另外的判断:如果实际存储的字符串内容所占的字节数小于等于127就用1字节记录长度,大于127就用2字节记录长度。

因为如果理论最大值超过了255,那么在读长度的时候就会不知道读取的当前字节是长度的中间部分还是开始部分,为了区分,mysql在设计的时候为第一个比特位做了特殊处理,如果是0就说明该字节是单独长度记录,如果是1就说明该字节与下一字节俩一起作为长度记录。因为多占用了一个比特位来处理,所以第一个比特位最多只能存储0到127位的长度。

2、Null值列表上

与上面的变长长度列表存在的原因一样,可以设置为空的字段也需要一个列表来记录存储到底是哪个字段的值为空。null值列表的存储顺序和变长字段长度列表一样,是与实际设置的字段顺序相反的,用一个比特位来记录是否是空值,1为空值,0不为空值。八比特位组成一个字节,也就是最后存储的时候是用字节来存储的。

3、记录头信息

记录头信息用固定的5字节也就是40比特位来记录。具体的比特位使用内容如下:

image.png

image.png 说明:

  1. mysql在执行完delete后并不会立马删除数据而是将修改delete_mask字段,先做逻辑删除,为后面的修复数据提供可能。
  2. next_record记录的相对位置会跳到下一条数据的中间位置(额外信息和真实信息中间)

4、真实的数据

真实的记录其实除了存储我们设置的字段外还有一些其他的隐藏字段存在。

image.png 从图中看到有三个隐藏字段,分别是row_id,transaction_id,roll_pointer。其中只有row_id是非必须的,这和mysql的主键设置有关。

在mysql中如果我们设置了主键是什么那么就会按照我们设置的来当做主键,如果我们没有设置主键,那么mysql就会选择unique键来当做主键,而如果unique键也没有那么就会创建row_id来当做主键。

需要提一下的是如果我们的char类型字段使用的字符集是变长字符集,那么这个字段的长度也是可变的,也会存储到可变字段长度列表中去。

其他行格式

上面的内容都是来介绍COMPACT行格式的,下面将会简单介绍一下其他的行格式

Redundant行格式

image.png 这里的字段长度偏移列表和上面提到的变长字段长度列表不同,它存储的是所有字段的长度,存储顺序是与列的顺序相反,并且是存储的偏移量,通过计算相邻两数的差值来计算各列的长度。

行溢出

在某些时候一列的长度会超过其所能存储的最大值,这种时候的存储方法是这样的:先存储当前这一列所能存储的最大值,再加上指向其他页的地址,作为这一列的内容。指向的其他页地址用来存储其他超过长度的内容部分。这个页面也被称为溢出页。

有另外两种行格式提一下:Dynamic和Compressed行格式。这两种类似于COMPACT。不同点在于溢出页的处理。Dynamic会直接将所有信息都放在溢出页上,只在列上存放溢出页地址,Compressed则会对页面进行压缩来节省空间。