1. Buffer Pool 的 LRU 改进,midpoint insertion、young/old 区?
InnoDB Buffer Pool 采用经典 LRU 算法时存在哪些问题,其改进后的 LRU 机制(midpoint insertion、young/old 区)是如何工作的?
- 经典 LRU 的缺陷(全表扫描污染缓存、顺序读冲刷热点页)
- midpoint insertion 与 young/old 区(shorten the list 双向链表)
- innodb_old_blocks_time 与 innodb_old_blocks_pct 参数的作用
InnoDB 的 Buffer Pool 没有使用朴素的 LRU,而是采用改进的 LRU(Modified LRU)来避免全表扫描/大范围顺序读把真正的热点页挤出缓存。它将整个 LRU 链表按位置分为 young 区(链表头部,约 63%)和 old 区(链表尾部,约 37%,由 innodb_old_blocks_pct 控制)。新读入的页通过 midpoint insertion 插入到 young 与 old 的分界点(midpoint),而不是插入到链表头部。这样冷数据(如全表扫描的页)不会立刻占据头部,而是先进入 old 区;只有当页面在 old 区停留超过 innodb_old_blocks_time 毫秒后再次被访问,才会被提升(promote)到 young 区(链表头部)。当 new 页从 old 区提升到 young 区时,同时会从链表尾部淘汰一个最旧的页。这套机制保证了被频繁访问的真正热点页停留在头部,而被一次性扫描的页快速从 old 区被淘汰。
该设计是"分代 LRU"思想,用时间窗口(old 区停留时间)来区分"短暂访问"与"持续热点",从而避免顺序扫描造成的缓存污染。理解 midpoint 位置、提升条件(old 区停留超时被再次访问)与淘汰策略(old 区尾部淘汰)是回答重点。
-- 查看当前调优参数
SHOW VARIABLES LIKE 'innodb_old_blocks_pct'; -- 默认 37,old 区占比
SHOW VARIABLES LIKE 'innodb_old_blocks_time'; -- 默认 1000ms,访问后停留时间