持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天
之前提到了数据库中的多种存储引擎,不同的存储引擎底层记录的处理、储存形式也不同,但是从原理上来说,万物皆通
这里我们要介绍的是最常见的InnoDB
也就是说
这是关于InnoDB一条记录的故事
记录的格式
同样的信息,可以有不同的存储形式(格式)
就像一句 “我爱你” 可以用不同的语言演绎
InnoDB中有4中格式:
- COMPACT行格式
- Redundant行格式
- Dynamic行格式
- Compressed行格式
可以在创建、修改表的时候,指定表的行格式
COMPACT行格式
一条(行)完整的记录:
- 记录的元数据信息
-
- 变长字段长度列表:主要是针对数据长度不固定的数据类型,需要存储其真正占用的字节数
-
- 整行记录的变长字段长度按列逆序存放在这个字段
- 变长字段为NULL时,不会存储长度
- 当该表列中没有变长字段的时候,不会有这个字段
- VARCHAR为变长字段类型
- CHAR使用字节长度不固定的字符集时,也是变长字段类型
- CHAR(M)会分配足够存储M长度字符的空间,VARCHAR则不会
- NULL值列表:统一管理值可能为NULL的列
-
- 先会看当前表定义中,哪些列可为NULL
- 若表中没有可为NULL的列,则没有该字段
- 每一列为一个二进制位(1为NULL,0部位NULL),按列顺序逆序排列
- 该字段以字节为单位,不满时高位补0
- 记录头信息:用于描述记录的其他信息
-
- 预留位1、预留位2:各1bit
- delete_mask:1bit,记录是否删除
- min_rec_mask:1bit,B+树每层叶子节点中最小记录会有该标记
- next_record:16bit,下一条记录相对地址
- ......
- 记录的数据信息:每一列的数据
-
- 除了自定义列数据,还有些隐藏列:
-
- row_id:行id,记录的唯一标记
- transaction_id:事务id
- roll_point:回滚指针
- 主键选取规则:自定义主键→选取一个Unique键做主键→没有Unique键,添加row_id做主键
元数据信息就是告诉你,你应该怎么解读存储的二进制数据信息、数据信息的存储规则,这样才能置换出真是的数据信息
Redundant行格式
MySQL5.0之前的数据格式了,有点老了
- 记录的元数据
-
- 字段长度偏移信息:所有列的逆序偏移信息,第一位表示当前记录是否为NULL
-
- 定长字符串还是会占据空间存储空信息
- 记录头信息:就是记录头信息,少个record_type,多了个n_feild、1byte_offs_flag
- 记录的数据
Dynamic、Compressed行格式
和COMPACT格式很像,只是在处理行溢出的时候使用的策略不一样
会将溢出的字段所有数据存储在溢出页,该字段只存储溢出页地址
行溢出
任何东西都不能无限膨胀
MySQL中的一条记录大小也是如此
- 除了BLOB、TEXT类型列,其他列占用的字节数加起来不能超过65535个字节
-
- 实际上只要存储了很大的数据都有可能出现行溢出现象
- 只会在该字段存储部分数据,剩余的数据在其他页存放,并且该字段使用20个字节存储其他存放地点的地址以及数据长度
交换的基本单位
内存中的数据存储断电后会失效
磁盘中的数据断电后不会丢失
为了长时间存储数据、在内存中处理数据,两者之间的数据交换是必不可少的
- 交换一次数据过少时
-
- 交换频率增加
- 效率降低
- 交换一次数据过多时
-
- 数据丢失可能性更大
在InnoDB中叫数据划分为页,页大小一般为16KB,页为数据交换的基本单位