前置知识:
数据页是什么?
MySQL 进行的数据的最小操作是以数据页为单位。加载数据,最低加载一个数据页,不是加载指定的数据行,将内存的数据刷回硬盘的时候,也是最低回刷一个数据页。数据页里面包含着多个数据行。
数据页的详细结构
数据页是 MySQL 开发人员设计出来的一种特殊的数据结构。数据页的结构大致如下:
| 文件头 38个字节 |
|---|
| 数据页头 56个字节 |
| 最大记录 最小记录 26个字节 |
| 多个数据行 长度不固定 |
| 空闲区域 长度不固定 |
| 数据页目录 长度不固定 |
| 文件尾部 8字节 |
数据行:数据页内的数据行按照主键的大小进行排列。
页目录 : 数据行实际上是被分散存储在不同的槽位里面的,每一个槽位存放着一组数据行;页目录里面就存放着每个数据行的主键和对应的槽位。是一个 key-value 的映射关系。
数据写入数据页的过程
- 基于 free 链表空的数据页加载到缓存页中,数据页和缓存页一一对应。
- 数据写入缓存页的数据行区,数据行区的空间会变大一些,空闲区域变小一些。
- 基于 flush 链表 和 LRU 链表,将缓存页刷回磁盘的数据页中。
当一个数据页写满以后,就会写第二个数据页,这个过程叫做页分裂。为了保证下一个数据页的数据行的主键都大于当前数据页,在页分裂的过程中,会将下一个数据页中主键比上一个数据页最大主键小的数据移动到上一个数据页,将当前数据页中主键大于下一个数据页中的主键的数据行移动到下一个数据页。
所以在不断写入数据行的过程中,会增加数据页。如果主键不是自增的,在增加数据页的过程中,会有一个数据移动的过程,来保证下一个数据页的主键值都大于上一个数据页。
数据区
为了方便管理数据页,MySQL开发人员又设计了数据区和数据组的概念。
连续的64个数据页,就组成了一个数据区(extent)。每个数据页是16K,所以一个数据区的大小为16K * 64 = 1M 。
每256个数据区组成一个数据组。
表空间
在创建数据表的时候,在磁盘上都会有对应的文件”表名.idb”。表空间就是对应着磁盘上的一些这样的数据文件。数据区和数据组都存储在表空间里面。在表空间里面,第一个数据组的第一个数据区的前3个数据页,都是固定不变的,用来存放一些描述性的信息。
例如 FSP_HDR 这个数据页,存放了表空间和这一组数据区的一些属性。
IBUF_BITMAP 数据页存放这一组数据页的所有 insert buffer 的一些信息。
INODE 数据页,也是存放一些特殊的信息。
表空间的其它各组的数据区,每一组数据区的第一个数据区的前2个数据页也是存放特殊信息的。例如 XDES 数据页存放这一组数据区的一些相关属性等等。
整个表空间和的结构大致如下:
