mysql查询缓存的配置与性能提升

来源:这里教程网 时间:2026-02-28 20:49:24 作者:

MySQL 5.7 中 query_cache_type 和 query_cache_size 怎么设才生效

MySQL 5.7 默认已禁用查询缓存(

query_cache_type=0
),即使你把
query_cache_size
设成 256M,缓存也不会工作。必须同时满足两个条件:一是
query_cache_type
设为
1
(ON),二是
query_cache_size
>
1048576
(即至少 1MB)——小于这个值会被 MySQL 自动置为 0。

常见错误是只改了

query_cache_size
却忘了开
query_cache_type
,或者在配置文件里写成了
query_cache_size = 256
(单位是字节,实际只配了 256 字节)。

query_cache_type=1
:按需缓存(SELECT 不加
SQL_NO_CACHE
才考虑缓存)
query_cache_type=2
:只缓存带
SQL_CACHE
提示的语句,更可控但需改代码
query_cache_size
必须是 1024 的倍数,否则启动时被截断
修改后必须重启 MySQL(不是
SET GLOBAL
就能热生效)

什么样的 SELECT 语句根本不会进查询缓存

不是所有 SELECT 都能被缓存。只要语句里出现以下任一情况,MySQL 会直接跳过缓存逻辑:

含用户变量:
SELECT @x := 1
调用非确定性函数:
NOW()
UUID()
RAND()
USER()
访问系统表:
information_schema
performance_schema
表名带数据库前缀但当前库不匹配:
SELECT * FROM test.t1
而当前
USE
的是
otherdb
使用
LOCK IN SHARE MODE
FOR UPDATE
结果集超过
query_cache_limit
(默认 1MB)

尤其注意:哪怕只是

SELECT COUNT(*) FROM t WHERE created_at > NOW() - INTERVAL 1 DAY
,因为有
NOW()
,每次执行都会绕过缓存,形同虚设。

开启查询缓存反而变慢?关键瓶颈在哪

查询缓存不是“开就快”,它在高并发写入场景下会成为性能杀手。核心问题在于:任何对表的写操作(

INSERT
UPDATE
DELETE
TRUNCATE
)都会导致该表所有缓存条目被立即失效,并触发全局锁(
QUERY CACHE LOCK
)。

这意味着:一张被频繁更新的热点表(比如订单表),它的缓存命中率极低,但每次写操作却要花时间清理缓存 + 拿锁,反而拖慢整体吞吐。

可通过以下方式验证是否被反噬:

SHOW STATUS LIKE 'Qcache%';

重点关注三个指标:

Qcache_hits / (Qcache_hits + Com_select)
Qcache_lowmem_prunes > 0
→ 内存不够,频繁淘汰旧缓存
Qcache_inserts
接近
Com_select
→ 几乎每条 SELECT 都尝试缓存,但很快被清掉

MySQL 8.0+ 完全移除了查询缓存,替代方案是什么

MySQL 8.0 直接删掉了整个查询缓存模块(

query_cache_type
等参数已废弃),官方明确表示:在大多数真实负载下,它带来的锁竞争和维护开销远大于收益。

如果你正从 5.7 升级到 8.0,别试图找“等效替代参数”——没有。应转向更现代的优化路径:

用应用层缓存(Redis / Memcached)控制缓存粒度和失效逻辑 善用索引覆盖、延迟关联、物化视图(通过汇总表)减少重复计算 对固定参数的报表类查询,用
CREATE TABLE ... AS SELECT
预生成快照
启用
innodb_buffer_pool_size
(通常设为物理内存 70~80%)提升数据页缓存效率,这比查询缓存更底层、更稳定

真正容易被忽略的是:很多人升级后还在监控

Qcache_hits
,殊不知这个状态变量在 8.0 里压根不存在了——检查前先确认版本和参数是否已被弃用。

相关推荐