mysql 8.0+已彻底移除查询缓存;5.6/5.7虽保留但默认禁用且应全局关闭,需同时设query_cache_type、size、limit为0,并持久化配置。

MySQL 8.0 及以上版本已彻底移除查询缓存,配置无效;5.6/5.7 版本虽支持,但默认不启用,且强烈建议全局禁用——不是配不好,而是设计上就不该用。
怎么确认你的 MySQL 还有没有查询缓存
别只看 have_query_cache 是 YES 就以为能用:它只表示“编译时支持”,不代表开启。真正要查的是运行时行为:
-
SHOW VARIABLES LIKE 'query_cache_type'—— 值为0表示关闭;1表示全局启用;2表示仅对带SQL_CACHE的 SELECT 生效 -
SHOW VARIABLES LIKE 'query_cache_size'—— 即使type=1,若此值为0,缓存仍不会分配内存 -
SHOW STATUS LIKE 'Qcache%'中的Qcache_hits是否增长?零增长 +Qcache_inserts有值,说明缓存写入但几乎没被命中
为什么 SQL_NO_CACHE 不一定绕过缓存
SQL_NO_CACHE 看似是“开关”,实际在多个环节可能失效:
- 客户端驱动(如某些旧版 JDBC)或中间件(如 ProxySQL)可能静默剥离该 hint,导致语句仍进缓存
- 在
query_cache_type=2(DEMAND 模式)下,SQL_NO_CACHE无意义——只有显式写SQL_CACHE才会缓存 - MySQL 5.7 中,若语句含
@user_var、NOW()、RAND()等非确定性元素,即使写了SQL_NO_CACHE,服务器也根本不会尝试缓存,但你误以为“加了就安全”
彻底禁用查询缓存的三步操作(5.6/5.7 必须做全)
只设 query_cache_size = 0 不够:MySQL 仍保留元数据结构,带来轻微开销和潜在干扰。必须同步关闭三个开关:
SET GLOBAL query_cache_type = 0SET GLOBAL query_cache_size = 0SET GLOBAL query_cache_limit = 0
注意:这些是动态变量,重启后失效;如需持久化,需在 my.cnf 的 [mysqld] 段中添加:
query_cache_type = 0 query_cache_size = 0 query_cache_limit = 0
改完必须重启 mysqld 才完全生效。
替代方案比硬扛查询缓存更靠谱
与其花时间调 query_cache_size 或纠结 SQL_CACHE 写法,不如转向现代实践:
- 应用层用
Redis或Memcached缓存结果集——可控、可预热、可设置 TTL、支持复杂 key 结构 - 数据库内优先优化
WHERE条件、索引覆盖、避免SELECT *,比依赖查询缓存提升更稳定 - 读多写少场景,用主从分离 + 应用路由,把压力分散到从库,而非靠缓存“堵漏”
查询缓存的哈希键只认 SQL 字符串一字不差,不认语义、不认权限、不认事务隔离级别——这种粗粒度机制,在今天的数据一致性要求下,已经不是“调不好”,而是“不该存在”。











