MySQL 8.0 及以上版本已彻底移除 query_cache_type,无法启用;官方因高并发写入冲突而废弃整个查询缓存模块,相关变量和配置均无效。

MySQL 8.0 还能开 query_cache_type 吗?不能,它已被彻底删除
直接说结论:如果你用的是 MySQL 8.0 或更高版本,query_cache_type 这个配置项已从源码中移除,无论你怎么改 my.cnf、重启服务、执行 SET GLOBAL,都会报错或静默忽略——它不存在了。
这是官方明确的架构决策,不是 bug,也不是临时开关。MySQL 官方在 8.0 发布时就宣布废弃并移除了整个查询缓存(Query Cache)模块,原因是其设计与现代高并发、高写入场景严重冲突。
-
SHOW VARIABLES LIKE 'have_query_cache'在 8.0+ 中返回NO(不再是YES) -
SELECT @@query_cache_type会提示Unknown system variable 'query_cache_type' - 配置文件里写上
query_cache_type = ON不报错,但启动日志会警告 “option ignored”,且所有Qcache_*状态变量全部消失
5.7 及更早版本怎么开启 query_cache_type?别只设 type,size 必须非零
在 MySQL 5.7 或 MariaDB 10.3 等仍支持 Query Cache 的版本中,光设 query_cache_type = 1 是不够的——如果 query_cache_size = 0,缓存依然不工作。
这是因为 MySQL 把 query_cache_size 当作“是否启用”的实际开关:值为 0 时,即使 type 是 ON,也会跳过初始化缓存内存池。
- 必须同时配置:
query_cache_type = 1(或ON) +query_cache_size = 2097152(至少 2MB,太小会导致频繁Qcache_lowmem_prunes) - 修改后需重启 MySQL(
service mysql restart),SET GLOBAL只对size和type临时生效,且要求size已预先设为非零 - 验证是否真生效:
SHOW STATUS LIKE 'Qcache%'—— 如果返回空结果,说明没起来;如果Qcache_queries_in_cache> 0 且Qcache_hits持续增长,才算成功
为什么开了也白开?三个典型失效场景
即使配置正确,Query Cache 在真实业务中命中率往往极低,不是缓存没开,而是绝大多数查询根本不符合缓存条件。
- SQL 字符串必须**逐字节一致**:
SELECT * FROM user和SELECT * FROM user(多一个空格)算两条不同语句,各自缓存 - 含任何动态函数的查询一律不缓存:
NOW()、RAND()、CURRENT_USER()、SYSDATE()—— ORM 自动生成的带时间戳条件的查询基本全军覆没 - 只要表被
INSERT/UPDATE/DELETE修改过,该表所有缓存条目立刻清空;一张高频更新的order表,能让整个缓存池反复刷空
换句话说:它适合只读报表库,不适合任何有用户写入的 OLTP 场景。
替代方案不是调参,而是换思路:用 Redis 做应用层缓存
与其花时间调 query_cache_limit、分析 Qcache_free_blocks 碎片,不如把缓存逻辑上移到应用层——这里没有 SQL 字符匹配问题,也没有表级失效风暴。
- Spring Boot 可用
@Cacheable+RedisCacheManager,键名由方法签名和参数决定,可控性强 - 缓存粒度更细:可缓存单个用户信息(
user:1001),而不是整条SELECT * FROM user WHERE id=1001的结果集 - 失效更精准:更新用户时,只需
DEL user:1001,不影响其他用户或关联查询
MySQL 查询缓存是服务器级的“粗粒度自动缓存”,而 Redis 是应用级的“细粒度手动缓存”——后者需要多写几行代码,但换来的是确定性、可观测性和真实可用性。










