1.执行SQL时,数据在磁盘与缓存的交互原理
当执行CRUD操作的时候,会从磁盘上加载数据页到Buffer Pool的缓存页里去,然后更新了缓存页后,又会刷新回磁盘上的数据页里去。
在MySQL中进行数据操作的最小单位应该是数据页,而数据是一行一行的在磁盘和缓存中进行存储的。
2.数据页构成原理
这里要引入一个问题,每个数据页的默认大小是16kb,那么这16kb的大小就全用来存放所有的数据行了吗?
明显不是的,一个数据页拆分成了很多部分,主要包含了文件头、数据页头、最大记录和最小记录、多个数据行、空闲空间、数据页目录、文件尾部。
以下是数据页的结构简图:
在数据页的构成中,其文件头占据了38个字节,数据页头占据了56个字节,最大记录和最小记录占据了26个字节,数据行区域的大小是不固定的,空闲区域的大小也是不固定的,数据页目录的大小也是不固定的,然后文件尾部占据了8个字节。
MySQL通过这种特殊的存储格式在磁盘文件里去存放一个又一个的数据页,每个数据页在磁盘里实际存储的时候,就是包含了上述一些特殊的数据,然后每个数据页里还有专门的区域包含了多个数据行,至于每个数据行,这就是用前面描述的那套存储格式(一行数据的存储)来存储的了。
数据行区域不是一开始就有的
在把数据插入数据页之前,该数据页可能是空的,没有一行数据,也就是说这时候“多个数据行” 这一区域是空的。
假设现在要插入一行数据,若此时数据库里一行数据都没有,那么就会先从磁盘里加载一个空的数据页到缓存页里去。
此时空的数据页如上图所示,而加载数据页的过程如下图所示:
按照上图所示,由于缓存页跟数据页是一一对应的,我们将数据库在磁盘上的空数据页加载到Buffer Pool上的空缓存页之后,此时操作的就是缓存页了。
这里会向Buffer Pool中的空缓存页里插入一条数据,实际上就是在数据页那个区域里插入一行数据,然后空闲区域的空间就会减少一些,此时向缓存页里插入了一行数据之后。此时其缓存页结构如下图所示:
接着就可以不停的插入数据到这个缓存页里去,知道他的空闲区域都耗尽了,就是这个页满了,此时数据行区域内可能有很多行数据,如下图所示:
插入的数据在更新缓存页的同时,缓存页在lru链表里的位置也会不停的变动,可以肯定的是在flush链表里,最终它一定会通过后台IO线程根据lru链表和flush链表,把这个脏的缓存页刷到磁盘上去。
以上对数据页的整体存储结果的初步介绍。