当前位置: 首页 > news >正文

InnoDB对LRU算法的优化

标准 LRU 算法的核心思想是:当缓存空间不足时,淘汰掉最近最少使用的数据块(Page)。它通常用一个链表来实现,链表头部是最近访问的 Page,链表尾部是最久未访问的 Page。

然而,在数据库系统中直接使用标准 LRU 算法可能会遇到一些问题:

  1. 全表扫描 (Full Table Scan) 问题: 当执行一个大的全表扫描时,会读取并访问表中所有的 Page。这些 Page 会被依次加载到 Buffer Pool 中,并根据标准 LRU 算法被移动到链表的头部。这会很快地将 Buffer Pool 中原来存放的、真正“热点”的、频繁访问的数据 Page 推到链表尾部,导致它们被淘汰,然后后续需要再次访问这些热点数据时又需要从磁盘重新读取,性能下降。

  2. 预读 (Read-Ahead) 问题: InnoDB 有预读机制,会一次性读取多个 Page 到 Buffer Pool 中。这些 Page 可能后续并不会被立即访问,如果直接放入 LRU 头部,同样会污染缓存。

为了解决这些问题,InnoDB 并没有采用一个纯粹的 LRU 列表,而是对其进行了优化,主要思想是将 LRU 列表分成两个部分:

InnoDB 的优化 LRU 策略:新生代 (Young Generation) 和老生代 (Old Generation)

InnoDB 的 Buffer Pool 内部维护了一个 LRU 链表,但这个链表被逻辑上分成了两个区域:

  1. Young Generation (新生代): 存放的是最近经常被访问的热点数据 Page。位于整个 LRU 链表的头部。

  2. Old Generation (老生代): 存放的是访问相对较少的 Page,或者刚从磁盘加载进来但还没有被频繁访问的 Page。位于整个 LRU 链表的尾部。

这两个区域的比例是可配置的,通过 innodb_old_blocks_pct 参数控制,默认值是 37%,表示老生代占整个 Buffer Pool 的 37%,其余 63% 是新生代。

Page 如何进入和在列表中移动:

  • 新 Page 加载: 当一个新的 Page 从磁盘被读取到 Buffer Pool 中时,它通常不会直接进入 Young Generation 的头部,而是被放置到 Old Generation 的头部。这是为了防止全表扫描等操作带来的 Page 瞬间冲垮 Young Generation。

  • 访问 Old Generation 中的 Page: 当访问一个已经在 Buffer Pool 中、且当前位于 Old Generation 的 Page 时:

    • 如果该 Page 在进入 Old Generation 后,距离首次访问它的时间还没有超过 innodb_old_blocks_time 设定的阈值(默认是 0 毫秒),那么它不会被移动到 Young Generation,仍然留在 Old Generation 的原位。这可以防止那些只被短暂扫描(如一次性顺序读)访问的 Page 立即晋升。

    • 如果该 Page 在进入 Old Generation 后,距离首次访问它的时间已经超过了 innodb_old_blocks_time 设定的阈值,那么该 Page 会被移动到 Young Generation 的头部。这意味着它被认为是热点数据,成功晋升。

  • 访问 Young Generation 中的 Page: 当访问一个已经在 Buffer Pool 中、且当前位于 Young Generation 的 Page 时,它会被移动到 Young Generation 的头部。这是标准 LRU 的行为,确保最近访问的热点数据始终在链表的最前端。

  • 淘汰 Page: 当 Buffer Pool 空间不足需要淘汰 Page 时,总是从 Old Generation 的尾部 开始淘汰最久未使用的 Page。

这种优化带来的好处:

  1. 保护热点数据: 大量的、一次性访问的 Page(如全表扫描带来的)只会被加载到 Old Generation 的头部,它们需要在 Old Generation 中“冷却”一段时间并再次被访问后才有机会晋升到 Young Generation。如果它们后续没有被频繁访问,就会在 Old Generation 中逐渐向尾部移动并最终被淘汰,而不会污染和挤占 Young Generation 中真正的热点数据。

  2. 应对顺序扫描: innodb_old_blocks_time 参数进一步优化了顺序扫描的影响。即使 Page 进入了 Old Generation,如果只是短暂访问,也不会立即晋升,减少了 Young Generation 被不常用的 Page 占据的可能性。

  3. 提高缓存命中率: 通过将热点数据集中在 Young Generation,并在淘汰时优先淘汰老生代的 Page,提高了 Buffer Pool 对常用数据的缓存效率,从而提高整体性能。

相关的配置参数:

  • innodb_buffer_pool_size: Buffer Pool 的总大小。

  • innodb_old_blocks_pct: Old Generation 占 Buffer Pool 的百分比 (默认 37)。

  • innodb_old_blocks_time: Page 在 Old Generation 中首次访问后,需要等待多久(毫秒)才能在下次访问时被晋升到 Young Generation (默认 0)。

总的来说,InnoDB 的 LRU 优化通过引入 Young/Old 两代以及 Page 进入和移动的策略,有效地解决了标准 LRU 在数据库工作负载下可能遇到的“缓存污染”问题,使得 Buffer Pool 能够更有效地缓存真正的热点数据。

相关文章:

  • LangChain入门(二)安装开发环境
  • MCP 模型上下文协议配置MCP Server开发实践
  • Spark知识总结
  • AI在Java中的场景面试题深度解析
  • c++之使用 libdl.so 和 <dlfcn.h> 实现动态链接
  • MySQL 的ANALYZE与 OPTIMIZE命令
  • 【基础篇】static_config采集配置详解
  • 《无刷空心杯电机减速机选型及行业发展趋势》
  • 邮件分类特征维度实验分析
  • QT事件Trick
  • 临床试验概述:从定义到实践的关键要素
  • Docker的常用命令
  • 为什么MySQL推荐使用自增主键?
  • 密码杂凑算法HaoLooog512设计原理详解
  • TRex 控制台命令解析
  • C++:BST、AVL、红黑树
  • 【Android】SettingsPreferenceService
  • 网络协议之为什么要分层
  • Mamba2模型的实现
  • 《系统架构 - Java 企业应用架构中的完整层级划分》
  • 病人有头发,照护者不发疯:《黑镜》中的身体缺席与虚伪关怀
  • 金科服务:大股东博裕资本提出无条件强制性现金要约收购,总代价约17.86亿港元
  • 湖南华容县通报“大垱湖水质受污染”,爆料者:现场已在灌清水
  • 大理杨徐邱再审上诉案宣判:驳回上诉,维持再审一审判决
  • 物业也能成为居家养老“服务员”,上海多区将开展“物业+养老”试点
  • 美情报机构攻击中国大型商用密码产品提供商,调查报告公布