mysql 8.0.3起彻底移除query cache,相关变量全被删除,配置即报错;因其全局锁、字节级匹配、表级失效、低命中率(常低于5%)等设计缺陷无法修复,应改用应用层缓存或innodb buffer pool等替代方案。

MySQL 8.0 之后压根没有 query_cache_type 这个变量——不是“默认关了”,是代码里删干净了,配置里写它,MySQL 启动直接报错 Unknown variable 'query_cache_type'。
my.cnf 里还留着 query_cache_* 配置?服务根本起不来
从 MySQL 8.0.3 起,所有 Query Cache 相关变量(query_cache_size、query_cache_limit、query_cache_min_res_unit)全被移除。哪怕只写一行 query_cache_type = 0,mysqld 就会拒绝启动,并抛出解析错误。
- 升级前必须手动清理 my.cnf / my.ini 中所有以
query_cache_开头的行 - Percona Server 8.x、MariaDB 10.6+ 同样不识别这些配置,别指望兼容
- docker 或云数据库(如 RDS)若使用自定义参数组,也要检查并删除残留项
为什么不是“禁用”,而是“物理删除”?
Query Cache 的问题不是参数开关能修好的,它的设计缺陷已深入执行路径:
-
LOCK_query_cache是全局互斥锁,每次缓存查找/插入/失效都得抢这把锁,多核机器上反而卡死并发 - 缓存键基于 SQL 字符串字节级比对:
SELECT * FROM t WHERE id=1和SELECT * FROM t WHERE id = 1是两条完全不同的 key - 一张表执行一次
UPDATE,所有关联该表的缓存条目(不管 SQL 多长、多复杂)全部清空,且清空过程也持锁 - 预处理语句(
PREPARE/EXECUTE)、含用户变量(@x)、子查询嵌套较深的查询,一律绕过缓存
命中率长期低于 5%?那不是缓存,是开销税
官方实测和大量生产环境监控显示:Qcache_hits / Com_select 比值持续低于 0.1,说明每 10 次 SELECT 只有不到 1 次命中。但代价始终在线:
- 每次 SELECT 都要先走一遍缓存判断逻辑(即使
query_cache_size = 0,路径仍存在) - 内存块是静态分配的连续大块,碎片严重时,
FLUSH QUERY CACHE自身就吃 CPU - 这部分内存不归 InnoDB Buffer Pool 管,无法复用,纯属额外占用
- InnoDB Buffer Pool 已通过页级缓存 + LRU-K 实现更细粒度、更高命中率的数据访问优化
替代方案不是“换个缓存”,是换位置、换粒度、换控制权
Query Cache 失败的本质,是在 SQL 解析层强行做结果级缓存,却扛不住数据一致性压力。真正有效的做法是分层解耦:
- 应用层用 Redis / Memcached 缓存业务语义明确的结果(如
user:123:profile),可设 TTL、支持穿透保护、共享于多实例 - 连接层用 ProxySQL 做规则级缓存,支持
SELECT * FROM users WHERE id = ?这类带通配的匹配,还能按响应时间、状态码动态开关 - 数据库内聚焦索引与执行计划:90% 的“想靠缓存提速”的慢查,其实缺的是覆盖索引,或写了
ORDER BY RAND()这种天然反缓存操作
最常被忽略的一点:InnoDB Buffer Pool 的调优(innodb_buffer_pool_size)对读性能的影响,远大于任何结果缓存——它缓的是数据页,不是拼装好的结果集,更新时只需刷脏页,不牵连其他查询。











