InnoDB缓冲池真实命中率须用Innodb_buffer_pool_read_requests和Innodb_buffer_pool_reads实时计算,SQL为SELECT ROUND((1-b.Variable_value/a.Variable_value)*100,2) AS hit_rate FROM performance_schema.global_status a JOIN performance_schema.global_status b ON a.Variable_name='Innodb_buffer_pool_read_requests' AND b.Variable_name='Innodb_buffer_pool_reads';MyISAM需分读写计算Key_buffer命中率。

查Innodb_buffer_pool命中率别信SHOW ENGINE INNODB STATUS
那个Buffer pool hit rate只是最近1000次读的滑动窗口统计,重启后重置、高并发下抖动大,生产环境必须弃用。真实命中率得靠Innodb_buffer_pool_read_requests和Innodb_buffer_pool_reads两个状态变量实时计算。
执行这句SQL最稳妥:
SELECT ROUND((1 - b.Variable_value/a.Variable_value) * 100, 2) AS hit_rate FROM performance_schema.global_status a JOIN performance_schema.global_status b ON a.Variable_name = 'Innodb_buffer_pool_read_requests' AND b.Variable_name = 'Innodb_buffer_pool_reads';
- 必须用
performance_schema.global_status查,避免用INFORMATION_SCHEMA.INNODB_METRICS或子查询——后者容易因取值时间点错位导致分母/分子不同步 - 整除陷阱:MySQL默认整数除法会截断,所以显式用
ROUND(..., 2)或乘以1.0转浮点 - 刚调过
innodb_buffer_pool_size后别急着采样:异步resize期间Innodb_buffer_pool_pages_free持续波动,至少等2分钟再查,否则命中率偏低失真
MyISAM的Key_buffer命中率要分开看读写
MyISAM没有事务,它的缓存只管索引(key_buffer_size),不缓存数据文件。命中率得拆成读、写两部分算,不能混在一起:
- 读命中率:
(1 - Key_reads / Key_read_requests) * 100% - 写命中率:
(1 - Key_writes / Key_write_requests) * 100%
查原始值用:
SHOW STATUS LIKE 'Key%';
常见误判点:
-
Key_read_requests极低(比如Key_reads哪怕只有1次,读命中率也会暴跌到99%以下——这不是内存不够,是查询太稀疏,指标本身失效 - 命中率长期Key_reads每秒>5次,才说明
key_buffer_size确实小了,该调大 - MyISAM表在混合负载下极易锁表,命中率再高也扛不住一个慢
SELECT把整张表锁死,所以监控必须配合CHECK TABLE table_name定期验文件完整性
命中率高 ≠ 没I/O压力
99.3%看着很美,但若Innodb_buffer_pool_reads每秒稳定在40+,说明仍有大量热数据没进缓存,或者SQL在反复回表、排序、扫描。
- 配合
SHOW ENGINE INNODB STATUS\G里BUFFER POOL AND MEMORY段的Pages read和Pages created:前者远大于后者,代表LRU链表抖动严重,页被频繁淘汰重载 - MySQL 8.0.22+用
EXPLAIN FORMAT=JSON看语句的disk_reads字段,提前预估单条SQL磁盘压力 - 查
sys.statement_analysis里SUM_ROWS_EXAMINED高但SUM_ROWS_SENT低的语句——扫了几百万行只返回几行,这种才是真凶手
Buffer Pool碎片与chunk对齐影响监控准确性
MySQL 5.7+把Buffer Pool拆成多个innodb_buffer_pool_instances,每个instance又由若干innodb_buffer_pool_chunk_size(默认128MB)组成。这意味着:
-
Innodb_buffer_pool_pages_data / Innodb_buffer_pool_pages_total这个比值,只能反映整体水位,无法体现各instance是否负载不均——某个instance满载而其他空闲时,整体命中率仍可能虚高 - 如果
innodb_buffer_pool_size不是innodb_buffer_pool_chunk_size × instances的整数倍,末尾chunk会浪费空间,监控看到的pages_free可能长期卡在个位数,误判为“已满” - 查各instance真实使用情况,得用
SELECT * FROM information_schema.INNODB_BUFFER_POOL_STATS;,重点看PAGES_DATA和PAGES_FREE列
真正难的不是算出一个百分比,而是判断这个数字背后有没有掩盖页抖动、脏页堆积或SQL低效。Buffer Pool监控本质是读放大诊断,不是内存用量审计。


















