MySQL LRU内存淘汰机制

MySQL LRU内存淘汰机制

LRU算法简介

MySQL使用了LRU淘汰算法,LRU也就是least recently use,最近最少使用。

策略就是使用的缓存页就加到LRU链表的头部,只要修改或者查询过就会移到链表头部,最后淘汰LRU尾部的。

其实所谓的lru链表本质上就是一个双向循环链表,如下图:
在这里插入图片描述

LRU算法存在问题

1、空间局部性

操作系统级别的空间局部性原理:

spatial locality(空间局部性):也就是说读取一个数据,在它周围内存地址存储的数据也很有可能被读取到,于是操作系统会帮你预读一部分数据。

mysql也是存在存在预读机制的!

①、通过参数innodb_read_ahead_threshold控制,默认是56。这个参数表示如果顺序访问了一个区里的多个数据页,这里的多个就是56,就会触发预读机制,把下一个区中所有的数据页都加载到缓存页里。

②、通过参数innodb_random_read_ahead控制,默认是off。这个参数表示如果缓存了一个区的13个连续数据页,就会触发预读机制,把这个区里的页全都加载到缓存页里。

当你执行select * from xxx;时,如果表中的数据页非常多,那这些数据页就会一一将buffer pool中的经常使用的缓存页挤下去,可能留在lru链表中的全部是你不经常使用的数据。

综上你可以看到,所谓的预读机制的优势,实际上违背了lru去实现将最近最少使用的数据页刷入磁盘的设计初衷。

2、全表扫描

如果是全表扫描,会把全表都加载到buffer pool中,有可能就把LRU链表中经常访问的都挤到后面去,就有可能被淘汰。

如何优化呢?

既然有经常访问的数据,又有不常访问的数据,是不是可以在LRU链表中分区,对这两块数据分别管理。

基于冷热数据分离的LRU链表

MySQL中设计LRU链表,是将冷热数据分离,链表分为两部分,一部分是冷数据,一部分是热数据,冷热数据占比由配置项innodb_old_blocks_pct控制,默认为37,即37%是冷数据

在这里插入图片描述

数据分布

lru链表被Midpoint分成了new sublist和old sublist两部分。

其中new sublist大概占比5/8,old sublist占比3/8。

数据加载

数据页从磁盘加载到buffer时,先加入old sublist。

在这里插入图片描述

LRU列表中有一个Midpoint的位置,新读取到的数据页并不是直接放入到LRU列表的首部,而是放入到LRU列表的Midpoint位置,这个操作称之为Midpoint insertion stategy,也叫中间点插入策略。在默认配置下,该位置在LRU长度的5/8处,这也就是上面使用8个数据页的作用。

热数据加载

从old区到new区

数据页第一次被加载进BufferPool时在old区头部。 当这个数据页在old区,再次被访问到,会做如下判断

  • 访问的时间跟第一次访问的时间间隔相差1s以上,满足这个条件,则该页将会被放入new_lru列表的头部。

    也就会从old区进入到new区了。

  • 这个存在时间由innodb_old_blocks_time控制,默认1000毫秒。

从new区到old区

随着冷数据查询变多或者热数据查询变多,相应的他们对应的两个区的大小也不一样。

不管是old区变长还是new区变长,只要每次区间长度变化时保证Midpoint始终指向5/8的位置,那么就可以保证old区占用3/8的空间。

如果new区变长,当Midpoint指针移动时,那么这时new区的空间就会部分转移到old区中。

热数据内部的移动

在热数据区域,如果一个缓存页被访问,不一定会立马移动到热数据链表的表头,因为频繁的移动链表也是有性能消耗的,因此,MySQL中设计为,如果热数据链表前25%(1/4)的缓存页被访问,他们是不会被移动的,只有在后75%(3/4)中的缓存页被访问,才会移动到表头,这样就能尽可能的减少链表中节点的移动,从而减小性能的损耗

计算过程

每一次移动会产生一个lock

两个重要参考:

freed_page_clock:Buffer Pool淘汰页数

LRU_new长度1/4

移动时机

当前freed_page_clock - 上次移动到Header时freed_page_clock>LRU_new长度1/4

说明:

  • 当热数据第一加入或者是上次移动到Header时会记录一个freed_page_clock
  • 再次访问到该数据的时候有一个当前的freed_page_clock
  • freed_page_clock 减去 上次移动到Header时freed_page_clock ,如果大于LRU_new长度1/4,则该页移动到LRU_new的表头

冷数据刷盘

什么时候将LRU链表中的冷热数据中的缓存页刷盘

定时刷盘,MySQL会起一个后台线程,运行定时任务,每隔一定的时间就将LRU链表的冷数据区域尾部的一些缓存页刷盘,然后清空这些缓存页,并放入free链表,从LRU链表删除,从Flush链表删除

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xianghan收藏册

极简精品作,一分也是一份鼓励哦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值