阿里面试题:MySQL为什么要改进LRU算法?

欢迎关注公众号:月伴飞鱼,每天分享程序员职场经验!

文章内容收录到个人网站,方便阅读:hardyfish.top/

资料分享

MySQL排错指南:

MySQL性能调优与架构设计:

普通LRU算法

LRU = Least Recently Used(最近最少使用):

也就是末尾淘汰法,新数据从链表头部加入,释放空间时从末尾淘汰数据。

当要访问某个页时,如果不在Buffer Pool中,需要把该页加载到缓冲池。

  • 并且把该缓冲页对应的控制块作为节点添加到LRU链表的头部。

当要访问某个页时,如果在Buffer Pool中,则直接把该页对应的控制块移动到LRU链表的头部。

当需要释放空间时,直接从末尾淘汰。

普通LRU算法的优缺点

优点:

  • 所有最近使用的数据都在链表表头,最近未使用的数据都在链表表尾,保证热数据能最快被获取到。

缺点:

  • 如果发生全表扫描(如使用select *等),则有很大可能将真正的热数据淘汰掉。
  • 由于MySQL中存在预读机制,很多预读的页都会被放到LRU链表的表头。
  • 如果这些预读的页都没有使用到的话,就会导致很多尾部的缓冲页很快被淘汰掉。

MySQL预读机制

线性预读linear read-ahead)。

参数innodb_read_ahead_threshold,默认值是56,意思是当加载数据页时,顺序的访问了一个区里的多个数据页。

如果访问的数据页的数量超过了这个阈值就会触发预读机制,会把相邻的区中的所有数据页都加载到缓存中。

随机预读randomread-ahead)。

innodb_random_read_ahead参数,默认时OFF,也就是关闭的。

当这个规则打开时,如果buffer pool里缓存了一个区中连续的13个数据页而且这些都是被经常访问的话。

就会将这个区其他的数据页都加载到缓存中去。在5.5中已经将这种预读方式废弃,默认是OFF。

  • 若要启用此功能,即将配置变量设置innodb_random_read_ahead为ON。

通过预读机制加载到buffer pool的数据如果都放到LRU链表的头部会导致其他被经常访问的数据移动到尾部从而被淘汰刷回到磁盘。

  • 这是很不合理的,因为通过预读机制加载的数据可能不会用到。

除了通过预读机制导致频繁被访问的缓存页被淘汰之外全表扫描也会导致这个情况。

  • 比如select * from xxx,不加where条件。

改进型LRU算法

将链表分为new和old两个部分,在添加新数据时并不是从表头插入。

而是从中间midpoint位置插入数据(也就是从磁盘中新读出的数据会放在冷数据区的头部)。

如果数据很快就被访问了,那么page就会移动到new链表头部。

如果数据没有被访问,会逐步向old尾部移动,直到淘汰。

冷数据区的数据页什么时候会被转到热数据区呢?

如果该数据页在LRU链表中存在的时间超过1s,就将其移动到链表头部(链表指的是整个LRU链表)

如果该数据页在LRU链表中存在的时间短于1s,其位置不变。

  • 由于全表扫描有一个特点,就是它对某个页的频繁访问总耗时会很短。

1s这个时间是由参数 innodb_old_blocks_time 控制的。

相关推荐
RISCV_Explorer1 小时前
RISC-V启动与运行时规范机制解析——BRS约定、HSM多核启动与设备树要求
后端·risc-v
星栈独行1 小时前
ADK-Rust 是什么?Rust 生态新一代 AI Agent 开发套件
人工智能·后端·rust
螺蛳粉 螺蛳粉2 小时前
MySQL 分布式集群系列 · 第五篇——全方位对比:NDB、MGR、主从复制、分库分表怎么选?
数据库·分布式·mysql
JavaGuide2 小时前
对标 MinIO!全新一代分布式文件系统正式发布
前端·后端
用户8356290780512 小时前
使用 Python 将 DOCX 转换为 Markdown
后端·python
IT_陈寒2 小时前
Vue computed属性这个坑,我居然踩了三次才爬出来
前端·人工智能·后端
TrebleZ3 小时前
为什么总爱问Java中怎么判断两个对象是相同的
面试
孙启超3 小时前
【AI开发之Rust】第 7 课:错误处理 —— panic、Result 与 `?`
人工智能·分布式·后端·爬虫·spring cloud·架构·rust
烈风逍遥4 小时前
第一篇:SeaPack 全栈项目工程化实践
前端·后端·架构
烈风逍遥4 小时前
第二篇:SeaPack 权限体系:从"谁都能看"到"该看什么看什么"
前端·后端·架构