mysql中的查询缓存与SQL执行的关系与影响

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

MySQL 查询缓存(query_cache)已彻底移除

MySQL 8.0 起,

query_cache_type
query_cache_size
等所有查询缓存相关变量和逻辑已被完全删除。如果你在 8.0+ 版本中执行
SHOW VARIABLES LIKE 'query_cache%'
,结果为空;设置
query_cache_type=1
会报错
Unknown system variable 'query_cache_type'
。这不是配置失效,而是代码级移除——它不再参与任何 SQL 执行流程。

5.7 及更早版本中,查询缓存如何干扰 SQL 执行

在启用查询缓存的旧版本中,一条 SELECT 语句的执行流程实际是:先查缓存 → 命中则跳过解析/优化/执行 → 直接返回结果。这带来几个关键副作用:

缓存键基于完整的 SQL 文本(含空格、大小写、注释),
SELECT * FROM t
select * from t
视为两条不同语句
只要表
t
发生任何
INSERT
/
UPDATE
/
DELETE
,该表关联的所有缓存条目立即失效
缓存命中时,
SQL_NO_CACHE
不生效;而加了
SQL_CACHE
的语句,即使结果集超大也会尝试缓存,可能拖慢整体性能
SELECT NOW()
SELECT RAND()
这类非确定性函数,每次执行结果不同,但旧缓存机制仍会缓存第一次的结果,导致数据错误

为什么现代 MySQL 彻底放弃查询缓存

根本原因是它在高并发写入场景下成为严重瓶颈:

缓存锁粒度粗:任意表更新都会触发全局缓存锁,阻塞其他查询缓存操作 内存碎片与管理开销大:缓存块分配/回收依赖全局 mutex,在多核机器上反而降低吞吐 收益极低:真实业务中,相同 SQL 文本重复执行比例远低于预期;而代价(锁争用、内存占用、失效风暴)却随写入量线性上升 替代方案更优:InnoDB 缓冲池(
innodb_buffer_pool_size
)对热数据页的缓存效率更高,且无语句级一致性负担

迁移或排查时必须检查的残留痕迹

升级到 8.0 后,若应用仍带

SQL_CACHE
SQL_NO_CACHE
提示,MySQL 会直接忽略它们——不报错,也不生效。但以下情况需手动处理:

配置文件(如
my.cnf
)中残留的
query_cache_type=1
等行,启动时会被静默跳过,建议彻底删除以免误导
监控脚本若还依赖
Qcache_hits
Qcache_inserts
等状态变量,会查不到值,需改用
Com_select
+
Innodb_buffer_pool_read_requests
等指标估算有效命中
ORM 或中间件生成的 SQL 若硬编码了
SQL_CACHE
,虽不影响运行,但属于冗余噪声,建议清理
SELECT /*+ NO_CACHE */ id FROM users WHERE status = 1;

上面这个注释在 MySQL 中无效——

NO_CACHE
不是 MySQL 支持的 optimizer hint;真正能绕过缓冲池读取的是
SELECT ... FOR UPDATE
或强制磁盘读的调试手段,但日常无需干预。重点始终是调优
innodb_buffer_pool_size
和索引设计,而不是怀念一个被删掉的功能。

相关推荐