mysql 8.0+ 已彻底移除 query_cache 模块,query_cache_type、query_cache_size 等配置无效,show variables like 'query_cache%' 返回空;官方因全局锁和粗粒度失效策略弃用,推荐用 redis、proxysql 或 innodb buffer pool 替代。

MySQL 8.0 以后 query_cache 已被彻底移除
直接说结论:query_cache_type、query_cache_size 这些配置项在 MySQL 8.0+ 版本中已不存在,启动时若配置会报警告,运行时查不到对应变量。官方明确废弃并删除了整个查询缓存模块。
原因很实际:全局锁 + 缓存失效策略太粗暴(任意表 DML 就清空全库该表相关缓存),高并发写场景下反而成性能瓶颈;同时 InnoDB 的 Buffer Pool 和更现代的客户端/代理层缓存(如 Redis、ProxySQL)更可控、更高效。
- MySQL 5.7 是最后一个支持
query_cache的稳定版本,但默认已禁用(query_cache_type=0) - 升级到 8.0 后如果应用还依赖查询缓存行为,会静默失效,可能引发意外负载升高
-
SHOW VARIABLES LIKE 'query_cache%'在 8.0+ 返回空结果,不是配置没生效,是压根没了
5.7 中开启 query_cache 的真实代价
即使你还在用 5.7,也不建议打开 query_cache,除非是只读从库且查询模式极其固定(比如报表类静态数据轮询)。
它不是“开就变快”,而是在特定条件下才可能省点 CPU,但代价是引入额外锁和内存碎片:
-
query_cache_type=1开启后,每个 SELECT 都要先加全局LOCK_query_cache,高并发下争抢严重 - 只要对某张表执行
INSERT/UPDATE/DELETE,所有命中该表的缓存条目全被清掉,不管是否相关 -
query_cache_size设太大(比如 >256MB)会导致初始化慢、内存分配卡顿,且无法动态调整 - 缓存键包含 SQL 字符串全量(含空格、大小写、注释),
SELECT * FROM t和SELECT * FROM t被视为两条不同查询
替代方案比硬扛 query_cache 更靠谱
与其调 query_cache_limit 或纠结 query_cache_min_res_unit,不如把精力放在更可控的缓存层级上:
- 应用层用
Redis缓存结果集,键可自定义(比如user:profile:123),失效粒度精准到记录 - 连接层用
ProxySQL做简单 SELECT 缓存,支持正则匹配、超时控制、按用户隔离 - InnoDB 层靠调优
innodb_buffer_pool_size(通常设为物理内存 70%~80%),让热数据常驻内存,减少磁盘 IO - 慢查询优先优化执行计划:加索引、改写 SQL、避免
SELECT *、限制LIMIT,比缓存治标更治本
检查和迁移时最容易忽略的一点
很多团队在升级前只扫了 my.cnf 里的 query_cache 配置,却漏掉了代码里隐式依赖它的逻辑——比如应用层看到重复 SQL 就默认“数据库会缓存”,于是不做本地缓存或降级处理。
真正麻烦的不是配置删不掉,而是那些没写注释、没人维护的“假设型代码”:
- ORM 中手动拼的 SQL 字符串,因空格/换行不一致导致缓存未命中,但开发以为命中了
- 监控脚本用
SHOW STATUS LIKE 'Qcache_hits'做健康判断,8.0 上这个值永远是 0,误判为“缓存失效” - 备份恢复后忘记重置
innodb_buffer_pool_size,误以为是“缓存没起来”,其实只是 Buffer Pool 还没预热











