MySQL 8.0 已彻底移除查询缓存,性能优化应聚焦 InnoDB Buffer Pool 命中率(innodb_buffer_pool_reads/innodb_buffer_pool_read_requests),而非过时的 Qcache 指标。

MySQL 查询缓存(Query Cache)已弃用,别再依赖它做性能优化
MySQL 8.0 已彻底移除 query_cache_type 和相关参数,5.7 是最后一个支持它的稳定版本。如果你还在查 Qcache_hits、Qcache_inserts 这类状态变量,说明你可能正踩在一个过时的优化思路上——缓存命中率 ≠ 实际性能收益,尤其在写多读少或表频繁变更的场景下,查询缓存反而会成为锁争用瓶颈。
真正影响 SQL 执行性能的缓存层是 InnoDB Buffer Pool
现代 MySQL 性能分析应聚焦 innodb_buffer_pool_reads(物理磁盘读)与 innodb_buffer_pool_read_requests(逻辑读请求)的比值,这才是衡量「热数据缓存效果」的关键指标:
SELECT
ROUND((1 - (ibp_reads / ibp_read_requests)) * 100, 2) AS buffer_pool_hit_rate
FROM (
SELECT
VARIABLE_VALUE AS ibp_reads
FROM performance_schema.global_status
WHERE VARIABLE_NAME = 'Innodb_buffer_pool_reads'
) r
CROSS JOIN (
SELECT
VARIABLE_VALUE AS ibp_read_requests
FROM performance_schema.global_status
WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests'
) req;-
Innodb_buffer_pool_reads > 0表示有磁盘 I/O,需关注是否 buffer pool 太小或查询未走索引 - 命中率长期低于 95% 通常意味着 buffer pool 不足,或存在大量全表扫描
- 该指标只反映页级缓存效果,不等同于“SQL 结果被缓存”,和旧版 Query Cache 完全无关
如何判断某条 SQL 是否真的从 Buffer Pool 中受益
单条语句无法直接看到“本次执行是否命中 Buffer Pool”,但可通过 EXPLAIN FORMAT=JSON + 执行前后状态差定位真实开销:
- 先执行
SHOW STATUS LIKE 'Innodb_buffer_pool_read%';记下Innodb_buffer_pool_read_requests和Innodb_buffer_pool_reads - 运行目标 SQL(确保无其他并发干扰)
- 再次执行
SHOW STATUS,观察Innodb_buffer_pool_reads是否增加:若增加,说明有页未命中,触发了磁盘读 - 配合
EXPLAIN FORMAT=JSON查看rows_examined和used_columns,确认是否走了预期索引
注意:Handler_read_* 系列状态(如 Handler_read_next)反映的是存储引擎扫描行为,不是缓存命中指标,勿混淆。
performance_schema 中可跟踪的缓存相关事件
想深入分析某类操作的内存/IO 模式,开启以下 instruments 后查 events_waits_history_long:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES' WHERE NAME LIKE 'wait/io/file/innodb/%' OR NAME LIKE 'wait/synch/mutex/innodb/%';
- 重点关注
wait/io/file/innodb/innodb_data_file—— 表示实际磁盘读写等待 -
wait/synch/mutex/innodb/buf_pool_mutex高频出现?说明 buffer pool latch 争用严重,可能是 buffer pool 过大且未启用innodb_buffer_pool_instances - 这些事件不会告诉你“缓存命中”,但能暴露缓存失效或争用的真实代价
Buffer Pool 的大小、实例数、预热策略、以及 SQL 是否能复用已有页帧,远比“缓存命中率”这个数字更能决定性能。盯着一个被废弃的指标,不如先确认你的 innodb_buffer_pool_size 是否设为物理内存的 50%–75%,以及有没有定期用 SELECT * FROM table LIMIT 1 类操作意外刷掉热页。











