MySQL 8.0 起已彻底移除 Query Cache,任何启用或调优 query_cache_type 或 query_cache_size 的操作均无效;其因高写入下缓存频繁失效、全局锁争用、SQL 字符串级键导致复用率低、不支持预编译等缺陷被弃用。

MySQL 8.0 起已彻底移除 Query Cache,不是“不推荐”,是“没了”——任何试图启用或调优 query_cache_type 或 query_cache_size 的操作,在 8.0+ 版本里直接无效。
为什么 MySQL 官方砍掉了 Query Cache
Query Cache 的设计逻辑是“SQL 文本完全一致 + 表无变更 → 直接返回缓存结果”。但现实中这成了性能毒丸:
- 所有对该表的
INSERT/UPDATE/DELETE都会清空该表关联的所有缓存项,高写入场景下缓存命中率趋近于零 - 缓存锁是全局互斥锁(
LOCK_query_cache),并发查询一多,线程全卡在等锁上 - 缓存键基于完整 SQL 字符串,
WHERE id = 1和WHERE id = 2视为两条完全不同的查询,无法复用 - 不支持 Prepared Statement、含用户变量(
@var)、子查询嵌套较深等常见模式,实际覆盖场景极窄
5.7 及更早版本还开着 query cache?赶紧关掉
如果你还在用 MySQL 5.7 且 query_cache_type = 1,它不仅没帮你提速,反而在拖慢整体吞吐。验证和关闭步骤如下:
- 查当前状态:
SHOW VARIABLES LIKE 'query_cache%';—— 关注query_cache_type和query_cache_size - 临时关闭(重启失效):
SET GLOBAL query_cache_type = 0; - 永久关闭:在
my.cnf中删掉或注释掉query_cache_type、query_cache_size、query_cache_limit等所有相关配置项 - 注意:
query_cache_size = 0不等于关闭,它只是把内存设为 0,但查询路径仍会走缓存判断逻辑,仍有开销
替代方案不是“换一个缓存”,而是换思路
Query Cache 的失败本质是“在错误层级做缓存”——它混在 SQL 解析层,却要承担数据一致性压力。真正有效的优化方向是分层剥离:
- 应用层缓存:对确定性高、更新不频繁的结果(如配置表、省市区列表),用
Redis或Memcached缓存序列化后的结果,控制粒度和过期策略 - 数据库连接层缓存:如
ProxySQL支持基于规则的查询结果缓存,可设置 TTL、支持通配匹配(SELECT * FROM users WHERE id = ?),比原生 Query Cache 实用得多 - 索引与执行计划优化:90% 的“想靠缓存提速”的查询,其实缺的是合适的联合索引或没避免
SELECT */ORDER BY RAND()这类杀手操作 - 查询拆分:把大而全的报表查询,拆成聚合中间结果(物化到汇总表)+ 应用层拼装,比缓存原始明细快且可控
Query Cache 的幽灵还在不少运维手册和老教程里游荡。真正要警惕的,不是“怎么调得更好”,而是“为什么它还在你的配置文件里”。










