1.数据页

MySQL中进行数据操作的最小单位就是数据页。数据页默认有16kb 的大小,包含了文件头、数据页头、最小记录和最大记录、多个记录行、空闲空间、数据页目录、文件尾部。
数据页.png
其中文件头占据38个字节,数据页头占据了56个字节,最大记录和最小记录占据了26个字节,数据区域的数据大小不固定,空闲区域的大小也是不固定的,数据页目录的大小也是不固定的,文件尾占据8个字节。

刚开始时,数据区域没有一行数据。假设我们现在要插入一行数据,此时先是从磁盘上加载一个空的数据页到缓存页里,然后在缓存页的数据区域里插入一行或者一批数据,直到空闲区域被耗尽。

2. 表空间

平时创建的表,都有一个表空间的概念,在磁盘上对应着一个”表名.ibd” 的磁盘文件。

简单来说在物理层面,表空间就是对应一些磁盘上的数据文件。

3. 数据区

在一个表空间的磁盘文件里,其实有很多数据页。数据页太多不方便管理,引入了数据区的概念,英文就是extent。

其中一个数据区对应着连续的64个数据页,每个数据页是16kb,所以一个数据区域是1mb,然后256 个数据区域被划为一组。

对于表空间来说,它的第一组数据区的第一个区域的前3个数据页,都是固定的,里面存放了一些描述数据。比如FSP_HDP 这个数据页,它里面存放了表空间和这一组数据区的一些属性。

其他各组数据区,每一组数据区的第一个数据区的头两个数据页,都是存放特殊信息的。

表空间.png

4. 总结

当我们在数据库中执行crud 的时候,必须先把磁盘文件里的一个数据页加载到内存的Buffer Pool 的一个缓存页里去,然后我们增删改查都是针对缓存页里的数据来执行的。

假设插入一条数据,那么会先看看往哪张表里插入数据,然后找到表空间,就可以定位到对应的磁盘文件。有了磁盘文件之后,就可以从里面找到一个extent组,找一个extent,接着从里面找一个数据页出来。这个数据页可能是空的,也可能已经有数据。

最后就可以把这个数据页从磁盘里完整加载出来,放入Buffer Pool 的缓存页里去。

接着crud 操作都可以针对缓存页去执行了,会自动把更新的缓存页加入flush 链表,然后更新他在lru链表里的位置,包括更新过的缓存页会从free 链表里拿出来,等等。

此时对于那些被更新过的缓存页来说,都会由后台线程刷入磁盘的。因为一个数据页的大小是固定的,所以一个数据页固定就是可能在一个磁盘文件里占据了某个开始位置到结束位置的一段数据,此时你写回去的时候也是一样的,选择好固定的一段位置的数据,直接把缓存页的数据页的数据写回去,就覆盖掉了原来的那个数据页。