关于Mysql的Buffer Pool详解(二)

本文详细介绍了MySQL Buffer Pool中的free链表、flush链表和LRU链表,以及基于冷热数据分离的LRU算法优化。free链表用于跟踪空闲数据页,flush链表记录待写入磁盘的修改页,而LRU链表则区分常用和不常用的数据页。当缓存页不足时,MySQL会根据LRU算法淘汰冷数据页。后台线程定期将冷数据和flush链表数据写回磁盘,释放空间。这一机制确保了高效的数据缓存管理。
摘要由CSDN通过智能技术生成

今天这篇就和大家讲解一下Buffer Pool里的free链表、flush链表、LRU链表以及mysql是如何基于冷热数据分离的方案,来优化LRU算法淘汰机制的

1.free链表是什么?有什么作用?

在了解free链表之前我们先思考一个问题:我们都知道buffer pool会将自己的内存空间划分成多个16kb大小的数据页用来缓存数据,当读取磁盘文件的时候,会将磁盘文件里的数据写入buffer pool。那么问题来了,磁盘文件写入缓存数据到buffer pool中的数据页时,是怎么区分哪些缓存页是空闲的,哪些是有数据的?总不能一个个的去判断吧?

这时候就需要我们的free链表出场了,没错,free链表的作用就是用来记录哪些缓存页是空闲状态的。

free链表本身是一个双向链表的数据结构,链表中每个节点就是一个空闲缓存页的存放地址,也就是说buffer pool中的所有空闲缓存页,都会被记录到free链表中。此外还会有一个基础节点,基础节点记录了free链表的节点数量以及头结点和尾节点的指针。
另外还有一点需要注意,这个free链表里的节点其实就是buffer pool里的描述数据块,只不过是在描述数据块里增加了两个指针,分别用来记录free链表的上下节点,因此不会出现free链表节点和描述数据块冲突的情况。为了方便大家理解,我花了一个结构图,如下:
在这里插入图片描述
当从磁盘读取完数据,此时会先从free链表获取一个空闲缓存页节点,将相关的一些数据写入缓存页的描述数据块中(数据页所属表空间,数据页编号等信息),然后将数据写入到缓存页,之后再将该节点从free链表中去除。

2.flush链表是什么?有什么作用?

同样,在了解flush链表之前,我们还是来思考一个问题:我们都知道buffer pool里的缓存数据有增删改查的磁盘数据,但是写入磁盘的时候,肯定只会写入修改过的数据到磁盘,而查询操作的数据是不需要写入磁盘的,因为根本没有意义,那么问题来了,buffer pool是怎么区分那些数据是需要写入到磁盘中的呢?

有请我们的flush链表闪亮登场!!!没错,这就是flush链表在buffer pool中的作用。

flush链表的数据结构和free链表几乎是一样的,也是双向链表结构,也是有个基础节点,记录了头尾节点和链表节点数量。他同样也是描述数据块,只不过是在描述数据块中增加了两个指针,分别记录了flush链表的上下节点。
凡是被修改过的缓存页,都会把描述数据块增加到flush链表中,后台会有IO线程去获取flush链表的节点,然后将数据写入到磁盘中,并在flush链表中移除。数据结构如下:
在这里插入图片描述

3.LRU算法淘汰机制

由前面我们可以得知,磁盘写入数据到缓存时,会先从free链表获取一个空闲缓存页,然后再将数据页写入缓存页,如我我们有大量的crud操作,大量获取空闲节点,是否会出现没有空闲节点的情况,答案肯定是会的。
那么出现这种情况需要怎么处理呢?这时buffer pool只能淘汰一些缓存页来供新的数据页使用,那么该淘汰哪些缓存页呢?假如我们现在有两个缓存页 ,我们的10个请求中有8个都会用到1缓存页,如果此时让我们淘汰一个,你会淘汰谁?脑子没问题的肯定是会淘汰缓存2啊,因为1缓存用到多啊,这就叫LRU算法淘汰机制。

4. LRU链表

回到刚才的问题,free链表里的空闲节点没有了,此时buffer pool需要淘汰一些缓存页来存储新的数据页,那么他就会根据LRU算法淘汰机制去淘汰一些缓存页,那么问题来了,buffer pool是怎么知道哪些缓存页是经常用到的,哪些是不经常用的?

有请LRU链表闪亮登场!!!没错,LRU链表的作用就是用来标识哪些缓存页常用,那些不常用。

LRU链表也是双向链表结构,也是有个基础节点,记录了头尾节点和链表节点数量。他同样也是描述数据块,只不过是在描述数据块中增加了两个指针,分别记录了LRU链表的上下节点。他也是描述数据块,在描述数据块里加了两个LRU链表的指针。
只不过LRU链表分两部分,一部分是热数据,另一部分是冷数据。大体结构如下:
在这里插入图片描述
Buffer Pool默认LRU链表里的冷数据是37%,也就是LRU链表的冷数据占总长的37%,并且是在链表后端,前端是热数据。
那么冷热数据是如何保存的呢?

首先数据页第一次加载到缓存的时候,缓存页会被放到冷数据的链表表头。当这个数据1s之后再次被访问,说明这个数据可能会被频繁访问,这个缓存页就会被保存到热数据的链表里,并且在冷数据里去除。这里需要注意,因为热数据链表里的数据是经常访问的数据,所以不适合频繁移动数据到表头,这样对性能不好,所以mysql这里做了一个优化,就是如果你是热数据前面的1/4缓存页被访问,他是不会被移动到链表表头的,只有后面3/4的数据被访问,才会将数据移动到热数据链表表头。这样可以尽可能的减少节点的移动次数。

5.关于入盘的知识点:

1.mysql会有后台线程,运行一个定时任务,每隔一段时间都会将LRU链表里的冷数据尾端的一些缓存写入到磁盘,并清空这几个缓存页,写入到free链表。
2.后台线程同时会在mysql不怎么繁忙的时候,把flush链表里的缓存数据写入到磁盘。然后这些缓存页就会在flush链表和LRU链表中移除,然后加到free链表中。
整体流程:
mysql一边不停的加载数据到缓存,不停的查询和修改缓存数据,free链表的缓存页不停的减少,flush链表的缓存页不停的增加,LRU链表的数据不停的在移动。另一边,后台线程在不停的把LRU链表的冷数据尾部缓存页和flush链表的缓存页写入磁盘,然后LRU链表和flush链表的缓存页在不断减少,free链表的缓存页在不断增加。

6.如果实在没有空闲缓存了怎么办?

可能会出现free链表都被使用了,flush链表有一大堆被修改的缓存页,LRU链表有一大堆的缓存,此时如果来了一个新的数据需要加入缓存中,mysql会怎么处理?

mysql这时就会从LRU冷数据链表中的尾端找到一个缓存页,这个缓存页一定是最不常用的缓存页,然后把它写入磁盘,清空缓存页,再把最新的缓存写到这个缓存页中。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值