本文正在参加「技术专题19期 漫谈数据库技术」活动
MySQL的Innodb引擎是基于磁盘存储的引擎,为了弥补磁盘存储的性能问题,Innodb有了缓存池的概念,其实就是基于内存分配空间给Innodb,然后,用户操作Innodb数据的时候不直接操作磁盘,先操作缓存数据,然后同步到磁盘当中,那同步的过程当中如果所有的都同步,可能会导致性能的问题,所以就需要有一个同步的策略,Innodb采用了LRU算法。
LRU算法介绍
LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。最常见的实现是使用一个链表保存缓存数据,详细算法实现如下:
Innodb的LRU算法
上面的LRU问题确实能够实现被访问频繁的页面存放到前端,访问不频繁的放到后端,但是还是会有一些弊端,当存在热点数据时,LRU的效率很好,但偶发性的、周期性的批量操作会导致LRU命中率急剧下降,缓存污染情况比较严重,这里的缓存污染指的是:\扫描数据量比较大的一个表时,有可能将整个表的数据都缓存到LRU链表里,淘汰掉其他有用的数据。所以Innodb还是需要对LRU算法进行一些调整的:
1、Innodb的LRU算法提供了两个链表,一个是旧数据缓存链表,另外一个才是热点数据链表,数据更新之后先放到就数据缓存链表当中,然后设置一个时间,如果超过这个时间,还是热点数据,就同步到真正的热点数据链表当中,这个时间再Innodb当中叫做 innodb_old_blocks_time,我们可以通过sql语句去设置他:
set global innodb_old_blocks_time=1000;
2、并且在innodb当中也不是直接将新访问的数据放到队列的顶部,而是放在中间部分,具体的位置通过一个midpoint来设置,可以通过命令查看:
mysql> show variables like "innodb_old_blocks_pct"\G;
*************************** 1. row ***************************
Variable_name: innodb_old_blocks_pct
Value: 37
1 row in set(0.01 sec)
这里的value37值的就是会先填充到链表的37%的位置上,当然也可以通过命令设置这个位置的:
set global innodb_old_blocks_pct=20;
所以还是绘图展示一下Innodb的LRU算法:
ok,关于Innodb的LRU算法,我们就先聊这么多,后续可以补充代码的实现部分,还是欢迎各位大佬多多指点。
本文正在参加「技术专题19期 漫谈数据库技术」活动