InnoDB 页

InnoDB 以页作为磁盘与内存传输单位, 一个页为 16KB.

InnoDB 行格式

目前有4种行格式:

  • Compact
  • Redundant
  • Dynamic
  • Compressed

还会有更多的行格式.

设置行格式

  1. CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称
  2. ALTER TABLE 表名 ROW_FORMAT=行格式名称
  3. mysql> USE xiaohaizi;
  4. Database changed
  5. mysql> CREATE TABLE record_format_demo (
  6. -> c1 VARCHAR(10),
  7. -> c2 VARCHAR(10) NOT NULL,
  8. -> c3 CHAR(10),
  9. -> c4 VARCHAR(10)
  10. -> ) CHARSET=ascii ROW_FORMAT=COMPACT;
  11. Query OK, 0 rows affected (0.03 sec)

Compact 行格式

image.png

记录的额外信息

变长字段长度列表

  • 按照字段顺序的逆序存放

例子:

列名 存储内容 内容长度 (十进制) 内容长度 (十六进制)
c1 ‘aaaa’ 4 0x04
c2 ‘bbb’ 3 0x03
c4 ‘d’ 1 0x01

image.png

在描述变长字符所占用的空间 (字节为单位) 时, 到底使用多少个字节来表示呢? 上例使用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 字段的长度:

image.png

  • 如果字段的字符集是变长字符集, 那么即使使用的数据类型是 CHAR(M), 那么也会将字符的个数写到变长字段长度列表中.
  • CHAR(M) 类型的列要求至少占用 M 个字节

NULL 值列表

  • 将 NULL 值同一存储
  • 如果所有字段不允许 NULL 值, 那么 NULL 值列表也不存在
  • 也是逆序存储, 按比特位
    • 0, 该列的值不为 NULL
    • 1, 该列的值为 NULL
  • 使用字节的整数个存储, 如图所示

image.png

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

记录头信息

  • 描述记录
  • 5个字节

image.png

记录的真实数据

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

image.png

注意:

  • 对于 CHAR(M) 类型的列来说,当列采用的是定长字符集时,该列占用的字节数不会被加到变长字段长度列表,而如果采用变长字符集时,该列占用的字节数也会被加到变长字段长度列表

Redundant 行格式

MySQL 5.0 之前的行格式.

image.png

字段长度偏移列表

  • 记录所有列的长度的信息, 逆序存放
  • 每个列的长度的读取方式
    1. 整序过来
    2. 每个列长度使用1字节或2字节
    3. len(i) = value(i) - value(i-1)
  • 字段长度偏移列表记录的其实是数据的起始字节数 (就是偏移)

使用1字节还是2字节的规则:

  • 记录的真实数据占用字节数 <= 127, 使用1字节
  • len > 127 && len < 32767, 使用2字节

记录头信息

  • 占用6字节

记录中的数据过多时

image.png