mysql 8.0 彻底移除了查询缓存模块,query_cache_type等所有相关变量均被删除,配置即报错;其设计存在全局锁、表级失效、sql字符串敏感三大硬伤;推荐用redis、innodb缓冲池或proxysql替代。

MySQL 8.0 的 query_cache_type 和 query_cache_size 配置根本不会生效——不是配错了,是 MySQL 已经把整个模块删了。
MySQL 8.0 启动就报 Unknown variable 'query_cache_type'
这不是配置语法错误,而是 MySQL 解析器压根不认识这个词。从 8.0.3 版本起,所有 query_cache 相关变量(包括 query_cache_limit、query_cache_min_res_unit)全被移除。Percona Server 8.x、MariaDB 10.6+ 同样不支持。配置文件里哪怕只留一行 query_cache_type = 0,服务就起不来。
常见误操作:
- 从 5.7 升级后没清理 my.cnf 里的 query_cache 配置项
- 照着老教程复制粘贴,却没注意文档日期是 2018 年
- 看到
SHOW VARIABLES LIKE 'query_cache%'返回空,还以为是“没生效”,其实是“不存在”
为什么宁可砍掉也不修?三处硬伤无法绕过
Query Cache 不是调参能救的,它的设计缺陷嵌在执行路径最底层:
-
LOCK_query_cache是全局锁:每次查缓存、写缓存、清缓存都要抢这把锁,多核机器上反而卡死并发 - 一张表
UPDATE一次,所有命中该表的缓存全清——不是按 SQL 清,是按表名暴力清,写越勤,缓存越像装饰品 - 缓存键等于 SQL 字符串全量哈希:多一个空格、大小写不同、注释位置变一下,就是全新缓存条目;
SELECT * FROM t和select * from t完全不共享
还在用 MySQL 5.7?也别急着开 query_cache_type = 1
5.7 默认就是 query_cache_type = 0,官方早就不推荐了。真要开,必须同时满足:
-
query_cache_size > 1048576(小于 1MB 会自动禁用) - 查询不能含
NOW()、USER()、用户变量@var、临时表、子查询中带UNION等非确定性成分 - 涉及的表在查询期间未被任何连接执行过
INSERT/UPDATE/DELETE
但即便全满足,高并发写入下 Qcache_lowmem_prunes 持续上涨、Qcache_hits 几乎为 0,才是常态。
替代方案不是“选一个”,而是分层用对地方
缓存不该堆在数据库内核里,而应落在更可控的层级:
- 热数据查得多、改得少(比如字典表):应用层用
Redis,key 自定义(如dict:status),失效粒度精准到单条记录 - 高频读、混合写场景:靠
innodb_buffer_pool_size缓数据页,设为物理内存的 70%–80%,比缓结果集更通用、更高效 - 想在 SQL 层做轻量缓存:用
ProxySQL,支持正则匹配、超时控制、按用户隔离,且不污染应用逻辑
真正容易被忽略的是:很多你以为“需要缓存”的慢查询,其实加个覆盖索引、去掉 SELECT *、避免 ORDER BY RAND() 就解决了——比折腾缓存来得直接。











