Buffer Pool 与命中率
InnoDB 把磁盘上的数据页缓存在内存的缓冲池(Buffer Pool)里,读写都先经过它。命中率指逻辑读中不必读盘的比例,常用算法是用 1 减去物理读除以逻辑读。它只是一个比例,判断内存是否够用要看物理读的绝对增长速度与 LRU 页面分布,而不是单看一个百分比。
基本信息
| 核心状态量 | Innodb_buffer_pool_reads(物理读)、Innodb_buffer_pool_read_requests(逻辑读) |
|---|---|
| 页面分布 | information_schema.INNODB_BUFFER_POOL_STATS,按池实例返回聚合行 |
| 池大小 | innodb_buffer_pool_size,8.0 默认 128MB,生产按可用内存的 50%~75% 设置 |
| 多池 | innodb_buffer_pool_instances 按实例切分缓冲池以减少内部争用 |
| 经验阈值 | 命中率长期低于 99% 通常说明池子偏小 |
典型使用场景
- 评估内存是否够用:读 IO 高时先确认是不是缓存装不下热数据
- 扩容前取证:用物理读增长速率证明瓶颈在缓冲池而不是磁盘本身
- 重启或主从切换后确认预热进度,再决定是否放开全量流量
- 定位全表扫描造成的缓存污染,观察 LRU 冷热端比例
- 对比主从实例的缓存效率,判断从库是否长期在冷缓存上跑
计算与查看
计算与查看
-- 命中率 = 1 - reads / read_requests
SHOW STATUS LIKE 'Innodb_buffer_pool_read%';
SELECT POOL_ID, POOL_SIZE, FREE_BUFFERS, DATABASE_PAGES,
MODIFIED_DATABASE_PAGES, PAGES_MADE_YOUNG, PAGES_NOT_MADE_YOUNG
FROM information_schema.INNODB_BUFFER_POOL_STATS;
-- 关键:看物理读的增长速率,先记一次,隔 60 秒再记一次
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads';
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';状态项逐项读法
| 指标 | 含义 | 异常信号 |
|---|---|---|
| read_requests | 逻辑读次数,反映整体访问压力 | 持续增长属正常,它只提供分母 |
| reads | 必须从磁盘读页的物理读次数 | 增长速率高说明热数据没装进内存 |
| FREE_BUFFERS | 空闲页数量 | 长期为 0 表示池已占满,此时扩容才有意义 |
| MODIFIED_DATABASE_PAGES | 脏页数量 | 突然抬高预示刷脏压力大,写入可能抖动 |
| PAGES_MADE_YOUNG | LRU 中被提升到热端的页数 | 持续偏高说明热端竞争激烈 |
| PAGES_NOT_MADE_YOUNG | 被判定为冷页、未提升的页数 | 激增常伴随全表扫描冲刷缓存 |
命中率必须配合绝对值看:十万次物理读放在十亿次逻辑读里也是 99.99%,但足以压垮一块慢盘。判断标准是「每秒物理读」和磁盘 IO 利用率,不是比例本身。
缓冲区池大小不是越大越快,而是要能装下工作集;设置过大触发系统换页(swap)反而更慢。多实例时池大小会按实例均分,查看 POOL_SIZE 可以确认每片实际尺寸。
SHOW ENGINE INNODB STATUS 的 BUFFER POOL AND MEMORY 段同样有命中率,但那是累计值;刚重启的实例这段数字没有参考意义,必须先跑一段业务再评估。