MySQL 8.0 及以后版本完全删除了 Query Cache 功能,相关系统变量均已废弃;5.7 及更早版本也不推荐启用,因其缓存粒度粗、失效激进、易引发锁竞争,OLTP 场景下反而降低 TPS。

MySQL 查询缓存(Query Cache)在 8.0 中已彻底移除
直接说结论:MySQL 8.0 及以后版本**完全删除了 Query Cache 功能**,query_cache_type、query_cache_size 等所有相关系统变量均已废弃。如果你正在用 8.0+,任何试图开启或调优查询缓存的操作都会失败,配置文件里写上也会被忽略,启动时还会报警告。
即使你用的是 5.7 或更早版本,Query Cache 也**不推荐启用**——它在高并发写入场景下极易成为性能瓶颈,因为只要表有任意一行被修改,该表所有缓存的 SELECT 结果都会被清空,锁竞争严重。
为什么 MySQL 会废弃 Query Cache
核心问题在于它的缓存粒度太粗、失效太激进:
-
SELECT * FROM users WHERE id = 123和SELECT name FROM users WHERE id = 123被视为两个完全不同的查询,无法共享缓存 - 只要
UPDATE users SET status=1 WHERE id=123执行一次,整个users表相关的所有缓存条目全被清掉 - 缓存命中前需对 SQL 字符串做全量比对(大小写敏感、空格敏感),开销不小
- 多线程环境下,
query_cache_mutex锁常导致线程阻塞,QPS 上不去
实测表明:在 OLTP 场景下,开启 Query Cache 后 TPS 反而下降 10%~30%,尤其当写入频率 > 50 QPS 时,几乎毫无收益。
替代方案:用好 InnoDB 缓冲池和客户端缓存
真正有效的缓存不在 SQL 层,而在更合适的位置:
-
InnoDB Buffer Pool:确保
innodb_buffer_pool_size设置为物理内存的 50%~75%(仅限专用数据库服务器),它缓存的是数据页和索引页,复用率高、粒度细、无写失效风暴 -
应用层缓存:用 Redis / Memcached 缓存热点查询结果,比如
get_user_by_id:123,由业务控制过期逻辑,避免无效穿透 -
HTTP 层缓存:对只读接口(如商品详情页)设置
Cache-Control: public, max-age=300,让 CDN 或浏览器缓存响应 - 连接层缓存(如 ProxySQL):支持基于 SQL 模板的轻量级结果缓存,可配置 TTL 和条件过滤,比原生 Query Cache 更可控
如何确认你的 MySQL 是否还在用 Query Cache
执行以下命令快速验证:
SHOW VARIABLES LIKE 'have_query_cache';
如果返回 have_query_cache 值为 NO(8.0+ 默认),或 DISABLED(5.7 中显式关闭),说明它没起作用;若为 YES,再查:
SHOW STATUS LIKE 'Qcache%';
重点关注 Qcache_hits(命中数)和 Qcache_inserts(插入数),如果前者远小于后者,或者 Qcache_lowmem_prunes 持续增长,说明缓存频繁被挤出,实际价值极低。
真正要盯的指标其实是 Innodb_buffer_pool_hit_rate —— 它长期低于 95% 才值得优化,而不是纠结一个早已过时的机制。











