全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-15 12 分钟 ✍️ juanwangdev

Buffer Pool与LRU算法

Buffer Pool是InnoDB最重要的内存结构,缓存数据页和索引页,减少磁盘IO。

Buffer Pool结构

整体架构

SQL
┌─────────────────────────────────────────────────┐
│                  Buffer Pool                     │
├─────────────────────────────────────────────────┤
│  ┌─────────────────────────────────────────┐   │
│  │           Data Page Cache               │   │
│  │        (数据页/索引页缓存)                │   │
│  └─────────────────────────────────────────┘   │
├─────────────────────────────────────────────────┤
│  ┌─────────────┐ ┌─────────────────────────┐    │
│  │ Flush List  │      LRU List            │    │
│  │ (脏页链表)   │    (页面淘汰链表)          │    │
│  └─────────────┘ └─────────────────────────┘   │
├─────────────────────────────────────────────────┤
│  ┌─────────────┐ ┌─────────────────────────┐    │
│  │  Free List  │    Page Hash Map         │    │
│  │ (空闲页链表) │    (页哈希索引)           │    │
│  └─────────────┘ └─────────────────────────┘   │
└─────────────────────────────────────────────────┘

页面结构

SQL
每个数据页默认16KB
┌────────────────────────────────────┐
│ Page Header (页头)                  │
├────────────────────────────────────┤
│ Page Directory (页目录)             │
├────────────────────────────────────┤
│ Infimum + Supremum (最小最大记录)    │
├────────────────────────────────────┤
│ User Records (用户数据)             │
├────────────────────────────────────┤
│ Free Space (空闲空间)               │
└────────────────────────────────────┘

关键参数

SQL
-- Buffer Pool大小(建议设为物理内存的60%-80%)
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';

-- Buffer Pool实例数(大内存建议多实例减少竞争)
SHOW VARIABLES LIKE 'innodb_buffer_pool_instances';

-- 页大小
SHOW VARIABLES LIKE 'innodb_page_size';

改进的LRU算法

InnoDB对传统LRU算法进行了改进,解决全表扫描污染问题。

传统LRU问题

SQL
传统LRU问题:
全表扫描时,大量冷数据进入LRU头部
→ 热数据被挤出 → 缓存命中率下降

InnoDB改进LRU

将LRU链表分为两个区域:

SQL
┌─────────────────────────────────────────────────────┐
│                    LRU链表                           │
├─────────────────────┬───────────────────────────────┤
│   Young区域(热数据)   │      Old区域(冷数据)           │
│      (5/8)          │          (3/8)                │
│   长期活跃数据        │   新加载页/扫描页              │
└─────────────────────┴───────────────────────────────┘
         ↑                                    ↑
      MRU端                               LRU端
    (最近最多使用)                      (最近最少使用)

页面访问流程

text
1. 读取页面
   ↓
2. 页面在Buffer Pool中?
   ├── 是 → 直接使用,移动到Young区头部
   └── 否 → 从磁盘加载
       ↓
   3. Free List有空闲页?
       ├── 是 → 直接分配
       └── 否 → 淘汰LRU尾部页面
       ↓
   4. 新页面进入Old区头部(非Young区)
       ↓
   5. 再次访问该页面?
       └── 是 → 移动到Young区头部(成为热数据)

关键参数

text
-- Old区域占比(默认3/8=37%)
SHOW VARIABLES LIKE 'innodb_old_blocks_pct';

-- 页面在Old区停留时间阈值(默认1000ms)
SHOW VARIABLES LIKE 'innodb_old_blocks_time';

-- 调整建议(避免全表扫描污染)
SET innodb_old_blocks_time = 1000;
-- 扫描期间设置更大的值,扫描后恢复默认

页面管理机制

三大链表

链表作用
Free List空闲页面链表,等待分配
LRU List按访问时间排序的页面链表
Flush List脏页链表,等待刷盘

页面状态

text
┌────────────────────────────────────┐
│           Page States              │
├────────────┬───────────────────────┤
│    clean   │  干净页(未修改)       │
├────────────┼───────────────────────┤
│    dirty   │  脏页(已修改,待刷盘)  │
├────────────┼───────────────────────┤
│    free    │  空闲页(无数据)       │
└────────────┴───────────────────────┘

脏页刷盘策略

text
-- 脏页刷盘策略
SHOW VARIABLES LIKE 'innodb_flush_method';

-- 后台刷盘线程数
SHOW VARIABLES LIKE 'innodb_page_cleaners';

-- 脏页占比阈值(触发刷盘)
SHOW VARIABLES LIKE 'innodb_max_dirty_pages_pct';

性能监控

text
-- 查看Buffer Pool状态
SHOW STATUS LIKE 'Innodb_buffer_pool%';

-- 关键指标
Innodb_buffer_pool_read_requests  -- 逻辑读次数
Innodb_buffer_pool_reads          -- 物理读次数(缓存未命中)
Innodb_buffer_pool_wait_free      -- 等待空闲页次数
Innodb_buffer_pool_pages_dirty    -- 脏页数量

-- 缓存命中率计算
命中率 = 1 - (Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests)
-- 目标:> 99%

监控查询

text
-- 查看Buffer Pool内部状态
SELECT
    POOL_ID,
    POOL_SIZE,
    FREE_BUFFERS,
    DATABASE_PAGES,
    DIRTY_PAGES
FROM information_schema.INNODB_BUFFER_POOL_STATS;

调优建议

场景建议
物理内存充足Buffer Pool设为70%-80%物理内存
高并发写入增加innodb_buffer_pool_instances
全表扫描频繁增大innodb_old_blocks_time
脏页刷盘慢调整innodb_page_cleaners

Buffer Pool大小调整需要重启服务,建议一次性设置合理值。

要点总结

  • Buffer Pool是InnoDB核心缓存,存储数据页和索引页
  • 采用改进LRU算法,分为Young区和Old区防止全表扫描污染
  • 新页面先进入Old区,再次访问才进入Young区
  • 监控缓存命中率,目标>99%
  • 根据内存大小和业务场景调整Buffer Pool参数

📝 发现内容有误?点击此处直接编辑

← 上一篇 MySQL 逻辑备份与物理备份
下一篇 → InnoDB存储引擎
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库