InnoDB 页
InnoDB 以页作为磁盘与内存传输单位, 一个页为 16KB.
InnoDB 行格式
目前有4种行格式:
- Compact
- Redundant
- Dynamic
- Compressed
还会有更多的行格式.
设置行格式
CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称ALTER TABLE 表名 ROW_FORMAT=行格式名称mysql> USE xiaohaizi;Database changedmysql> CREATE TABLE record_format_demo (-> c1 VARCHAR(10),-> c2 VARCHAR(10) NOT NULL,-> c3 CHAR(10),-> c4 VARCHAR(10)-> ) CHARSET=ascii ROW_FORMAT=COMPACT;Query OK, 0 rows affected (0.03 sec)
Compact 行格式

记录的额外信息
变长字段长度列表
- 按照字段顺序的逆序存放
例子:
| 列名 | 存储内容 | 内容长度 (十进制) | 内容长度 (十六进制) |
|---|---|---|---|
| c1 | ‘aaaa’ | 4 | 0x04 |
| c2 | ‘bbb’ | 3 | 0x03 |
| c4 | ‘d’ | 1 | 0x01 |

在描述变长字符所占用的空间 (字节为单位) 时, 到底使用多少个字节来表示呢? 上例使用1字节来表示的 (01, 03, 04 都占用1字节)
W, M, L:
- W, 当前字符集每个字符最大占用空间
- M, 指 VARCHAR(M) 中的 M, 即字符的最大个数
- L, 实际字符的个数
InnoDB 读取 “变长字段长度列表” 规则:
- 如果
W*M <= 255, 那么使用1字节为距离来读 - 如果
W*M > 255- 如果
L <= 127, 使用1字节为距离来读 - 如果
L > 127, 使用2字节为距离来读
- 如果
查看字符集确定 W, 查看 varchar(M) 定义来确定 M.
变长字段长度列表不存储值为 NULL 字段的长度:

- 如果字段的字符集是变长字符集, 那么即使使用的数据类型是 CHAR(M), 那么也会将字符的个数写到变长字段长度列表中.
- CHAR(M) 类型的列要求至少占用 M 个字节
NULL 值列表
- 将 NULL 值同一存储
- 如果所有字段不允许 NULL 值, 那么 NULL 值列表也不存在
- 也是逆序存储, 按比特位
- 0, 该列的值不为 NULL
- 1, 该列的值为 NULL
- 使用字节的整数个存储, 如图所示

- 还是要查看表定义, 如果某列设置的 not null, 那么 NULL 值列表无须始终记录0
- 在变长字段长度列表存储需要两个条件:
- 是变长类型
- 不是 null
记录头信息
- 描述记录
- 5个字节

记录的真实数据
- MySQL 会添加一些隐藏列
| 列名 | 是否必须 | 占用空间 | 描述 |
|---|---|---|---|
| DB_ROW_ID | 否 | 6B | 行 ID, 唯一标识一条记录 |
| DB_TRX_ID | 是 | 6B | 事务 ID |
| DB_ROLL_PTR | 是 | 7B | 回滚指针 |
- 如果表没有主键, 也没有 unique 键, 那么 InnoDB 自动创建 DB_ROW_ID 列作为主键
- 其他两个会一直有

注意:
- 对于 CHAR(M) 类型的列来说,当列采用的是定长字符集时,该列占用的字节数不会被加到变长字段长度列表,而如果采用变长字符集时,该列占用的字节数也会被加到变长字段长度列表。
Redundant 行格式
MySQL 5.0 之前的行格式.

字段长度偏移列表
- 记录所有列的长度的信息, 逆序存放
- 每个列的长度的读取方式
- 整序过来
- 每个列长度使用1字节或2字节
- len(i) = value(i) - value(i-1)
- 字段长度偏移列表记录的其实是数据的起始字节数 (就是偏移)
使用1字节还是2字节的规则:
- 记录的真实数据占用字节数 <= 127, 使用1字节
- len > 127 && len < 32767, 使用2字节
记录头信息
- 占用6字节
记录中的数据过多时

