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

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 能够更有效地缓存真正的热点数据。

http://www.xdnf.cn/news/2964.html

相关文章:

  • 哪些CAD看图软件适合初学者使用?
  • Jackson 使用方法详解
  • Starrocks导入数据时报错too many versions
  • 网络安全之红队LLM的大模型自动化越狱
  • RAG当知识库非常大导致大语言模型不准确,该如何处理
  • 通过langchain访问大模型并实现简单的查询
  • 操作系统——第四章(文件管理与文件的逻辑结构)
  • power bi获取局域网内共享文件
  • arm设备树基础知识
  • “专精特新”中小企业数字化转型呈现 4 大转型特征
  • 同步时钟与异步时钟
  • 1.24g 雨晨 19045.5796 Windows 10 企业版 x64 极速版
  • pymsql(SQL注入与防SQL注入)
  • Spring反射机制
  • Dijkstra算法的学习
  • cmake qt 项目编译
  • 开源 Agent 框架对比:LangChain vs AutoGen vs CrewAI
  • 牛客:AB1 【模板】栈
  • 天猫TP代运营服务商-品融电商:助力品牌破局增长的专业推手
  • 【HCIA】4种NAT的配置方式
  • AI专题(二)----由浅入深初识LLM
  • 大模型性能测试
  • 数据要素如何驱动的新质IDC一体化运营体系发展?
  • Jtti:nginx服务器如何限制访问频率
  • 在android 系统上qnn sdk转换,运行模型示例
  • MCU低功耗运行模式与唤醒机制解析
  • 数据结构每日一题day12(链表)★★★★★
  • 【AI论文】PHYBench:大型语言模型中物理感知与推理能力的全面评估
  • Redis 常见问题深度剖析与全方位解决方案指南
  • 基于STM32、HAL库的DS2411R安全验证及加密芯片驱动程序设计