持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情
前言
InnoDB是将表中的数据存储到磁盘上的,所以即使关机后重启数据也不会丢失,而真正处理数据的过程是发生在内存中的,所以需要把磁盘中的数据加载到内存中,如果是处理写请求的话,还需要把内存中的内容刷到磁盘上,而我们知道磁盘的读写速度非常慢,和内存读写差了几个数量级,那么InnoDB是如何从磁盘上将一条一条的记录读出来?且听本文细细分解,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教。
InnoDB页简介
数据库管理存储空间的基本单位是页(Page),InnoDB将数据划分为若干个页, 一个页中可以存储多个行记录,InnoDB中页的大小默认为 16KB。
数据库I/O操作以页作为磁盘和内存之间交互的基本单位,也就是一次最少从磁盘中读取16KB的内容到内存中,一次最少把内存中的16KB内容刷新到磁盘中。也就是说,在数据库中,不论读一行,还是读多行,都是将这些行所在的页进行加载,这样会大大降低磁盘I/O操作,提高数据处理效率。
InnoDB为了不同的目的设计了许多种不同类型的页,比如存放表空间头部信息的页,存放Insert Buffer信息的页,存放undo日志信息的页等等。
数据页的结构
数据页被划分为7个部分,不同部分有不同的功能,下图为InnoDB数据页的结构:
文件头(File Header)
文件头固定占用38字节,存储的是各种类型页通用的信息。文件头中存储了页校验和、页号、上一页、下一页、页类型等。
文件头结构示意图如下:
当某个表数据量特别大时,会分散在多个不连续的页中,通过上一页、下一页可以组成一个双向链表来把同一个表中的数据串联起来。这样
页头(Page Header)
固定占用56字节,用于存储一个数据页中存储的记录的状态信息;比如本页中已经存储了多少条记录、第一条记录的地址是什么、页目录中存储了多少个槽等等,详细结构说明如下:
| 名称 | 占用空间大小 | 描述 |
|---|---|---|
| PAGE_N_DIR_SLOTS | 2字节 | 在页目录中的槽数量 |
| PAGE_HEAP_TOP | 2字节 | 第一个记录的地址 |
| PAGE_N_HEAP | 2字节 | 本页中的记录的数量(包括最小和最大记录以及标记为删除的记录) |
| PAGE_FREE | 2字节 | 指向可重用空间的地址(就是标记为删除的记录地址) |
| PAGE_GARBAGE | 2字节 | 已删除的字节数,行记录结构中delete_flag为1的记录大小总数 |
| PAGE_LAST_INSERT | 2字节 | 最后插入记录的位置 |
| PAGE_DIRECTION | 2字节 | 最后插入的方向 |
| PAGE_N_DIRECTION | 2字节 | 一个方向连续插入的记录数量 |
| PAGE_N_RECS | 2字节 | 该页中记录的数量(不包括最小和最大记录以及被标记为删除的记录) |
| PAGE_MAX_TRX_ID | 8字节 | 修改当前页的最大事务ID,该值仅在二级索引中定义 |
| PAGE_LEVEL | 2字节 | 当前页在索引树中的位置,高度 |
| PAGE_INDEX_ID | 8字节 | 索引ID,表示当前页属于哪个索引 |
| PAGE_BTR | 10字节 | 非叶节点所在段的segment header,仅在B+树的Root页定义 |
| PAGE_LEVEL | 10字节 | B+树所在段的segment header,仅在B+树的Root页定义 |
最大记录、最小记录(Infimum + Supremum)
是两条伪记录,都是由记录头(5字节)和8字节大小的固定部分组成。
用户记录(User Records)
对应表中的每一条数据,当插入一条数据时,会从“空闲空间”中申请对应大小的空间,划分到“用户记录”,并按照指定的行格式将数据存入其中。完整的记录数据中除了每个字段的真实数据外还会包含一些“额外信息”,不同的行格式“额外信息"也不相同。
空闲空间(Free Space)
页中尚未使用的部分,大小不确定。
页目录(Page Directory)
页中的记录相对位置,也就是各个槽在页面中的地址偏移量,大小不固定,插入的记录越多,这个部分占用的空间越多。
文件尾部(File Trailer)
8个字节组成,前4个字节是页的校验和,与文件头中的校验和对应,后4个字节代表页面最后修改时对应的日志序列位置(lsn)。
小结
数据库I/O操作以页作为磁盘和内存之间交互的基本单位,InnoDB中页的大小默认为 16KB,InnoDB将数据划分为若干个页, 一个页中可以存储多个行记录。 InnoDB为了不同的目的设计了许多种不同类型的页,一个数据页可以被分为7个部分,分别是:
- File Header,表示文件头,占固定的38字节。
- Page Header,表示页里的一些状态信息,占固定的56个字节。
- Infimum + Supremum,两个虚拟的伪记录,分别表示页中的最小和最大记录,占固定的26个字节。
- User Records:真实存储我们插入的记录的部分,大小不固定。
- Free Space:页中尚未使用的部分,大小不确定。
- Page Directory:页中的记录相对位置,也就是各个槽在页面中的地址偏移量,大小不固定,插入的记录越多,这个部分占用的空间越多。
- File Trailer:用于检验页是否完整的部分,占用固定的8个字节。