mysql 8.0.3起彻底移除query cache功能,相关变量(如query_cache_type、query_cache_size等)均被删除,配置残留将导致启动失败;其设计缺陷(全局锁、缓存失效粗放、碎片严重、sql字面匹配等)致无法修复,应改用应用层缓存(redis/memcached)、innodb buffer pool或proxysql等替代方案。

MySQL 8.0 配置文件里写了 query_cache_type 就启动失败
直接报错:Unknown variable 'query_cache_type',或者更隐晦地卡在启动阶段。这不是配置写错了,是 MySQL 8.0.3 起彻底删了这个功能——所有相关变量(query_cache_size、query_cache_limit、query_cache_min_res_unit)全被移除,连解析器都不认识它们。
- 如果你是从 MySQL 5.7 升级上来的,配置文件里残留的 query cache 参数必须全部删掉,否则服务起不来
- Percona Server 8.x、MariaDB 10.6+ 同样不支持,别指望“兼容保留”
- 哪怕只留一个
query_cache_type = 0,也会触发报错——它不是“禁用”,而是“不存在”
为什么 MySQL 宁可砍掉一个“缓存功能”,也不修它
不是不想修,是修不动。Query Cache 的设计缺陷深入骨髓,改起来比重写还难:
-
一把全局锁堵死并发:每次查缓存、写缓存、失效缓存,都得抢
LOCK_query_cache,多核机器上反而成性能瓶颈 -
一动就全废:对某张表执行一次
UPDATE,所有命中过这张表的 SQL 缓存全清——写越频繁,缓存越像摆设 - 内存越配越大,效率越跑越低:缓存块大小不一,碎片严重;清理时要遍历哈希表,“修剪”操作本身就很慢
-
SQL 必须字面完全一致才命中:
SELECT * FROM t和select * from t是两条不同缓存,空格、注释、参数位置差一点就 Miss
现在该用什么替代 Query Cache
不是“没了缓存就得硬扛”,而是换到了更合适的位置做缓存:
- 应用层优先用 Redis / Memcached:能控制过期策略、支持复杂 key、可共享、还能做热点穿透保护
-
InnoDB Buffer Pool 才是真·数据库级缓存:它缓的是数据页,不是结果集,读写混合场景下命中率高得多;调优重点应放在
innodb_buffer_pool_size -
查询本身要够“可缓存”:避免
SELECT *、加覆盖索引、减少ORDER BY RAND()这类天然反缓存的操作 - 连接层/代理层也能缓:比如 ProxySQL 支持基于规则的结果集缓存,粒度比原生 Query Cache 更可控
还在用 MySQL 5.7?那也别急着开 query_cache_type = 1
即使版本允许,开启 Query Cache 多数时候是负优化:
- 官方从 5.6 就默认关掉了(
query_cache_type = 0),因为基准测试显示:只要稍有写入,它就拖慢整体 QPS - 真正受益的场景极窄:纯静态报表库 + 几乎零更新 + 查询高度重复 + 结果集小且固定
- 如果真想试,务必同时设
query_cache_size = 0(禁用分配)+query_cache_type = 1(仅按需启用),再压测对比,别凭感觉
现在主流业务基本没几个符合这条件的。与其纠结怎么调 query_cache_min_res_unit,不如花十分钟把慢查加上索引,效果更稳。










