07.行记录结构
约 1536 字大约 5 分钟...
行记录分类:
CompactRedundant( < 5.0`)Dynamic(默认)Compressed
Compact 行记录结构:

记录的额外信息变长字段长度列表- 图示:

- 变长字段的定义:
VARCHAR(M)CAHR(M)但字符集为变长字符集(除了ascii、latin1、utf32之外都是,见文末的字符集编码)
- 按照变长列的顺序倒序排列
- 使用1~2个字节,记录的是对应列
真实占用的字节数W表示当前字符集的最多字节数(utf8mb4 1~4)VARCHAR(M)这种类型表示能存储最多M个字符(注意是字符不是字节)- 该类型理论最多占用的字节数就是
M×W - 实际占用字节数计做
L - 结论:
- M×W <= 255
- 用1个字节表示
- M×W > 255,L <= 127
- 用1个字节表示
- M×W > 255,L > 127
- 用2个字节表示
- M×W <= 255
- 图示:
Null值列表
- 按照Null值列的顺序倒序排列
- 用bit位记录的是对应列是否为Null,需要是字节的整数,不足在高位补0
记录头信息- 图示:

- 结构如下:
- |名称|大小(单位:bit)|描述| |:--😐:--😐:--😐 |
预留位1|1|没有使用| |预留位2|1|没有使用| |delete_mask|1|标记该记录是否被删除| |min_rec_mask|1|B+树的每层非叶子节点中的最小记录都会添加该标记| |n_owned|4|表示当前Page directory分组拥有的记录数,仅分组内的最大记录存在该字段| |heap_no|13|表示当前记录在记录堆的位置信息| |record_type|3|表示当前记录的类型,0普通记录,1B+树非叶子节点记录,2最小记录,3最大记录| |next_record|16|表示下一条记录的相对位置|
- 图示:
记录的真实数据隐藏列- 图示:

- 结构如下:
- |列名|是否必须|占用空间|描述| |:--😐:--😐:--😐:--😐 |
row_id|否|6字节|行ID,唯一标识一条记录| |transaction_id|是|6字节|事务ID| |roll_pointer|是|7字节|回滚指针,指向undo记录| - 补充:
- **
InnoDB主键的生成策略 **:- 优先使用用户自定义主键,否则2
- 选取一个
Unique键作为主键,否则3 - 为表默认添加一个名为
row_id的隐藏列作为主键
- **
- 图示:
用户数据列- 真实的用户数据
Redundant 行格式:

Dynamic 行格式:
- 行溢出时处理方式跟
Compact存在差异,其他类似
Compressed 行格式:
- 行溢出时处理方式跟
Compact存在差异,其他类似;多页面进行压缩算法,节省空间,但消耗更多CPU
行溢出:
MySQL对一条记录占用的最大存储空间是有限制的(BLOB、TEXT除外,但会发生行溢出)所有列(不包括隐藏列和记录头信息)占用的字节长度在语法上加起来不能超过65535个字节(否则语法报错),在使用上超过8098字节会发生行溢出(不影响使用,语法不报错)VARCHAR(M)理论存储的字符数量:
- M 表示存储的字符个数,不是字节数
- ASCII编码, M的最大值:
- VARCHAR(M) NOT NULL, M最多为65533 = (65535-2)/1
- 字节数最多为65535个
- 字段值长度占2字节
- ASCII每个字符需要1个字节
- VARCHAR(M) 没有定义NOT NULL, M最多为65532 = (65535-2-1)/1
- 字节数最多为65535个
- 字段值长度占2字节
NULL值标识占1个字节- ASCII每个字符需要1个字节
- VARCHAR(M) NOT NULL, M最多为65533 = (65535-2)/1
- 不同编码下的M最大值:

行溢出:单个记录数据超过页的大小限制:- TEXT、BLOB类型的列在存储数据非常多的时候也会发生
行溢出 - 例如:VARCHAR(65532) 65533约64KB,超过单页16KB(16384字节)的限制
- 行记录格式针对
行溢出的方案:- 对于
Compact、Reduntant,如果某一列中的数据非常多的话,在本记录的真实数据处只会存储该列的前768个字节的数据和一个指向其他页的地址,然后把剩下的数据存放到其他页中。 - 对于
Dynamic、Compressed行格式,不会在记录的真实数据处存储数据的前768个字节,而是把所有的字节都存储到其他页面中,只在记录的真实数据处存储其他页面的地址 Compact、Reduntant行溢出:
Dynamic、Compressed行溢出:
- 对于
行溢出的临界点计算:- 假设:表结构只有一个字段(行记录只有一列)
- 规定:一个页中至少存放两行记录
- 数据推导:
- 每个记录至少27个额外字节;27 * 2
- 每个页的额外信息,136个字节
- 每个页最大16384字节
- 公式: 136 + 2×(27 + n) > 16384
- 求解后:n > 8098
- 如果我们向一个行中存储了很大的数据(超过8098个字节)时,可能发生
行溢出的现象
- TEXT、BLOB类型的列在存储数据非常多的时候也会发生
字符集:
MySQL有四个级别的字符集和比较规则:服务器级别、库级别、表级别、列级别
字符集 CHARSET:
- 作用:某个字符范围的编码规则
- 查看命令:SHOW CHARSET
- utf8mb3 (别名utf8):阉割过的utf8字符集,只使用1~3个字节表示字符,包含常用字符
- utf8mb4:正宗的utf8字符集,使用1~4个字节表示字符,包含所有字符
比较规则 COLLATION:
- 用来做排序和比较大小
- 查看命令:SHOW COLLATION [LIKE 匹配的模式]
字符集占用字节数: |字符集名称|Maxlen|备注| |:--😐:--😐:--😐 |
ascii|1|128个字符| |latin1/ISO 8859-1字符集|1|256个字符| |gb2312|1~2|兼容ASCII,ASCII占1个字节,其他2字节,| |gbk|1~2|对GB2312字符集的扩充| |Unicode字符集|1~4|收录所有能想到的字符| |utf8|1~4|unicode字符集的一种编码方式| |utf16|2、4|unicode字符集的一种编码方式| |utf32|4|unicode字符集的一种编码方式|