MySQL 8.0 起查询缓存已彻底移除,相关变量和监控指标(如 Qcache_hits)均无效;应转而关注 InnoDB 缓冲池命中率(1 - Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests),并优化 SQL 执行计划与索引。
MySQL 8.0 起,query_cache_type、query_cache_size 等所有查询缓存相关变量已被删除。执行 SHOW VARIABLES LIKE 'query_cache%' 将返回空结果;设置它们会报错 Unknown system variable。这意味着你无法再通过 Qcache_hits / (Qcache_hits + Qcache_inserts) 这类公式计算“查询缓存命中率”——因为那个缓存根本不存在了。
如果你还在监控 Qcache_hits 或依赖 mysqladmin extended -r -i 1 | grep Qcache,说明你可能:
innodb_buffer_pool)指标当成查询缓存指标InnoDB 缓冲池(innodb_buffer_pool)才是 MySQL 实际用到的核心缓存。它的“命中率”反映的是热数据是否常驻内存,直接影响磁盘 I/O 压力。计算公式为:
1 - (Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests)
其中:
Innodb_buffer_pool_reads:缓冲池未命中、必须从磁盘读取页的次数(越低越好)Innodb
_buffer_pool_read_requests:总逻辑读请求数(包括命中和未命中)健康阈值通常应 > 99%。低于 95% 就值得排查:innodb_buffer_pool_size 是否太小?是否有大范围全表扫描?
实时查看命令示例:
mysql -e "SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_%reads';"
过去靠查询缓存“掩盖”慢查询,现在每条语句都真实执行。优化必须落到 SQL 层面:
EXPLAIN 检查 type 字段:避免 ALL(全表扫描),优先 const/ref/range
key 列是否用了预期索引;key_len 是否符合联合索引最左匹配WHERE user_id = '123'(字段是 INT)会导致索引失效ORDER BY 和 LIMIT 组合时,确保排序字段在索引中覆盖,否则触发 Using filesort
一个典型陷阱:SELECT * FROM orders WHERE status IN ('paid','shipped') ORDER BY created_at DESC LIMIT 20 —— 若没建 (status, created_at) 联合索引,即使 status 有单列索引,仍大概率走全表扫描+临时文件排序。
应用端和中间件的缓存行为,往往比数据库内置机制更关键:
maxLifetime 和 idleTimeout 设置不当,会导致频繁重连,掩盖真实 SQL 性能问题@Cache)若未合理配置 timeToLiveSeconds,可能返回陈旧数据,或因缓存击穿引发 DB 突增查一条 SQL 很快,但线上接口 P99 延迟飙升?先确认是不是缓存层失效导致流量洪峰直接压到了 MySQL 连接数和缓冲池上。