MySQL基于冷热数据分离优化的LRU刷盘策略
前言
对于计算机刷盘这个概念相信大家都非常熟悉了,刷盘策略,其实在操作系统层面来说的话就是页面置换算法。
不知道各位朋友们还记得页面置换算法有哪些吗?
- FIFO(先进先出算法)
- OPT(最佳置换算法)
- LRU(最近最少使用算法)
- CLock(时钟置换算法)
- LFU(最不常用算法)
- MFU(最常使用算法)
因为MySQL中刷盘使用的是LRU算法,所以本文重点讲述LRU。。
LRU和LFU的区别
在正式开始MySQL刷盘策略讲解之前,有一点必须要和大家一起回顾的。
LRU算法和LFU算法是两回事:
- LRU算法(最近最少使用),强调的是最后一次使用的时间与当前启动刷盘的时间之间的间隔
- LFU算法(最不经常使用),强调的是在刷盘前的一段时间内使用的次数最少
简单的LRU刷盘策略
什么是LRU算法:
简单点来说就是,有维持一条链表,每访问一个数据页就将其移动到表头,这样在链表尾的就一直是当前时刻的最近最少使用的页面。
这样子,有什么缺点吗?
其实本来这算法已经挺好的了,主要思想是在缓存页不够的时候,挑最近最少使用的数据页进行刷盘以释放该缓存页,但是——
问题就出现在MySQL是一个庞大而复杂的系统,简单点来说,它并没有这么简单。
主要问题有两个:
- MySQL的预读机制,导致“间接被访问”的数据页也被加到了链表头
- MySQL走全表扫描的时候,会将大量页面移动到链表头
MySQL的预读机制就类似于局部性原理,你访问了数据页1 系统会认为你很有可能要访问数据页2,所以自动帮你加载进了内存。
全表扫描的话,肯定也是要将磁盘中的数据页加载进内存的。
因为这两个问题的存在,会导致原本经常访问的数据页被预读(或者全表扫描)进来的数据页挤到了链表尾,最终被淘汰掉
这是一个很大的影响性能的问题。
基于冷热数据分离优化
在这种情况下,我们将数据划分为两大类:一类是热数据,一类是冷数据。
热数据部分是实际需要访问的,而冷数据部分就是MySQL预读机制顺带的,或者是全表扫描的。
在这里插入图片描述
到了这里,相信各位朋友可能会有些疑惑:冷数据究竟什么时候才可以移动到热数据区呢?因为冷数据区是在LRU链表的末尾,所以肯定是先淘汰的冷数据区的数据页。
其实这个是有一定讲究的,你们想想假如刚从磁盘加载进来的时候,就立即访问了,那么这个时候是不是应该将冷数据移动到热数据区呢?
万一只是刚刚访问一次呢?之后都不访问了?比如全表扫描,一般都是扫描过后就不再访问了的。
那这样岂不是又出现问题了!
所以——
冷数据移动到热数据区的时机:
在冷数据被从磁盘加载到内存中,1s后还被访问这才会将该冷数据移动到热数据区。
为什么是1s之后呢?
因为全表扫描1次访问中1s已经可以完成了,只有1s之后还继续被访问到这才说明该数据页是热数据。
++++
在文章的最后,我再设问一句:热数据区内,是所有被访问的数据都需要移动到链表头吗?
其实热数据区比较靠前的哪些数据都是经常需要访问的,没必要每次都移动到链表头。
要知道链表结点的移动也是设计到性能消耗的,可以说能不动就不动。
为此,MySQL中采取的方案是:
将热数据也分为两部分,前四分之一是一部分,后四分之三是另一部分;只有访问后四份之三的时候才会将该数据页移动到链表头。
嘿嘿,各位朋友们,咱们今天的学习就到此结束了,为每一个坚持学习下来的你们点赞!
文末我再问一个问题:热数据区的数据不是所有都需要移动到链表头的,那么冷数据呢?访问冷数据是不是一定要将数据移动到冷数据区的最前面呢?
们,咱们今天的学习就到此结束了,为每一个坚持学习下来的你们点赞!
文末我再问一个问题:热数据区的数据不是所有都需要移动到链表头的,那么冷数据呢?访问冷数据是不是一定要将数据移动到冷数据区的最前面呢?
欢迎评论区讨论~