MySQL是如何对LRU算法进行优化的?又该如何对MySQL进行调优?

扫描下方二维码或者微信搜索公众号菜鸟飞呀飞,即可关注微信公众号,阅读更多Spring源码分析Java并发编程Netty源码系列MySQL工作原理文章。

微信公众号

1. 开篇

MySQL 在查询数据时,对于 InnoDB 存储引擎而言,会先将磁盘上的数据以页为单位,先将数据页加载进内存,然后以缓存页的形式存放在「Buffer Pool」中。Buffer Pool 是 InnoDB 的一块内存缓冲区,在 MySQL 启动时,会按照配置的缓存页的大小,将 Buffer Pool 缓存区初始化为许多个缓存页,默认情况下,缓存页大小为 16KB。

为了方便理解,对于磁盘上的数据所在的页,叫做数据页,当加载进 Buffer Pool 中后,叫做缓存页,这两者是一一对应的

在 MySQL 启动初期,Buffer Pool 中的这些缓存页都是处于空闲状态,也就是还没有被使用,而随着 MySQL 的运行时间越来越长,这些缓存页渐渐地都被使用了,用来存放从磁盘上加载的数据页,导致空闲的缓存页就越来越少。当某一时刻,所有空闲的缓存页都被使用了,那么这个时候,从磁盘加载到内存中的数据页该怎么办呢?

2. LRU算法

既然没有空闲缓存页了,而又想使用缓存页,那么最简单的办法就是淘汰一个缓存页。应该淘汰谁呢?当然是淘汰那个最近一段时间最少被访问过的缓存页了,这种思想就是典型的 LRU 算法了。

LRU 是 Least Recently Used 的简写,这个算法的实现就是淘汰最久未使用的数据,它通过维护一个链表,每当访问了某个数据时,就将这个数据加入到链表的头部,如果数据本身存在于链表中,那么就将数据从链表的中间移动到链表的头部,这样最终下来,在链表尾部的数据一定就是最久未被使用的数据了,因此可以将其淘汰。

将 LRU 算法应用到缓存页的淘汰策略上,那么就是在 InnoDB 存储引擎层内部,维护了一个链表,这些链表中的元素存储的就是指向缓存页的指针。

在 MySQL 启动的时候,这个链表为空。MySQL 启动以后,在进行数据查询时,InnoDB 会先判断要查询的数据所在的数据页,是否存在于 Buffer Pool 的缓存页当中,如果不存在,就从磁盘中读取对应数据页,存放到 Buffer Pool 一个空闲的缓存页当中,然后将这个缓冲页放入到链表的头部;如果要查询的数据已经存在于 Buffer Pool 当中了,那么就将对应的缓存页从链表的中间移动到链表头部。

这样随着 MySQL 的运行,空闲的缓存页越来越少,LRU 链表越来越长,直到某一时刻,剩余的空闲缓存页数为 0,当需要申请一个新的空闲缓存页的时候,就需要淘汰一个缓存页了,此时只需要把链表尾部的那个缓存页刷入到磁盘,然后清空缓存页里面的数据,这样就空余出一个新的缓存页了。

3. LRU 链表带来的问题

咋一看,似乎 LRU 链表完美解决了缓存

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值