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和索引设计,而不是怀念一个被删掉的功能。
