空间管理
InnoDB Disk I/O
InnoDB使用异步磁盘IO,创建许多控制IO操作的进程,从而在进行其他数据库操作的同时依然能够把内容写到磁盘里。在进程内部,写入操作依然是同步的,并不是使用系统原生的异步IO API。
Read-Ahead
InnoDB认为部分数据有可能会很快用到时,会将其从磁盘载入内存中(Buffer Pool),为实现大块连续读,InnoDB有两种策略
- 连续Read-Ahead,如果InnoDB注意到相关语句对某个tablespace的段访问是连续的,它会将整段内容提前载入到内存中
- 随机Read-Ahead,如果InnoDB注意到直接载入一整个tablespace会更快,它会直接把整个tablespace载入内存
Doublewrite Buffer
见前文中有关内容
File Space Management
InnoDB中的数据库存在文件中,所有内容写在一个文件还是分开写,都使用tablespaces的配置决定
Pages, Extents, Segments, and Tablespaces
Page
Page是数据库的最小磁盘空间管理单位,其尺寸默认为16K,可以修改。其结构为
名称 | 长度/字节 | 说明 |
---|---|---|
File Header | 38 | 页的通用信息 |
Page Header | 56 | 数据页专有信息 |
Infimum+supremum | 26 | 两个虚拟行记录 |
User Records | Not Fix | 实际存储的行记录 |
Free Space | Not Fix | 空闲空间 |
Page Directory | Not Fix | 某些记录的相对位置 |
File Tail | 8 | 校验 |
Extents
Extents是由许多Page组成的空间管理单位,其尺寸对照表如下
Page尺寸 | Extent尺寸 | Extent中的Page数 |
---|---|---|
4K | 1M | 256 |
8K | 1M | 128 |
16K | 1M | 64 |
32K | 2M | 64 |
64K | 4M | 64 |
Segment
Segment是由Extent构成的更高一级的单位。在InnoDB中,Tablespace的“文件”被称为Segment,注意,这个Segment和Rollback Segment什么的不一样,但是Rollback Segment会包含很多个Tablespace中的Segment。当Segment的空间不足时,InnoDB会先申请32 Pages,如果还需要申请,则会申请1个Extent。当Segment变得过大,InnoDB会一次获取4个Extents以保证数据的连续性。
一个Tablespace中包含两个Segment,一个用于存非叶子节点,一个用于存叶子节点,以保证叶子节点读写的连续性。
一些Page保存的是其他page的bitmap,所以有的时候Segment中只会包含零散的几个页而非整Extent。
删除操作的时候,会依据是否释放整Page或是整Extent来决定释放空间;删除表和行可以释放空间,但只在purge后空间才会被释放。
Page and Row
最长的行长度应当小于页的一半,如果出现过长的行,该行会被存在扩展页外存储(External off-page)中,直到其长度能被一页存下再挪回页中。
Row
行结构
- 变长字段长度列表: 存储着所有变长字段的数据占用的字段长度
- NULL标志位: 可以为NULL的列与标记为NULL的列
- 记录头信息
- 列1
- 列2
- …
记录头信息格式如下
名称 | 大小/bit | 描述 |
---|---|---|
预留位 | 2 | 没用 |
delete_mask | 1 | 删除标记 |
min_rec_mask | 1 | 非叶子节点中的最小记录 |
n_owned | 4 | 当前记录的记录数 |
heap_no | 13 | 当前记录在堆中的位置信息 |
record_type | 3 | 记录类型,0:叶节点,1:非叶子节点,2:最小记录,3:最大记录 |
next_record | 16 | 下一条记录的相对位置 |
External off-page
- COMPACT and REDUNDANT: 当数据在Page中放不下时,InnoDB会在Page中存前768个字节,并将其他数据存到溢出页中,每个列都有自己的溢出页。该768个字符的前20个记录了该数据的长度以及多于内容在溢出页中的指针。
- DYNAMIC and COMPRESSED: InnoDB只会在Page内存20个字符的内容,表示长度和指针。
Checkpoints
InnoDB只会小批量地将Buffer Pool中的内容写到磁盘中以避免对用户体验造成影响。