MySQL 8 查询缓存已废除详解:从架构、历史到替代方案

MySQL 8 查询缓存已废除详解:从架构、历史到替代方案

结论先行 :MySQL 8.0 已彻底移除 Query Cache(查询缓存)功能

若你在 5.7 或更早版本中见过 "命中查询缓存直接返回结果",那在 8.0 之后已不复存在。

本文将系统讲解:为什么移除、怎么验证、有哪些替代方案


🧾 一、官方确认:Query Cache 在 MySQL 8.0 中被移除

在 MySQL 官方文档中明确说明:

The Query Cache has been removed from MySQL 8.0.

--- 来源:MySQL 8.0 Reference Manual - Query Cache

✅ 实验验证

你可以在终端中执行:

sql 复制代码
SHOW VARIABLES LIKE 'query_cache%';
  • MySQL 5.7 输出示例:
Variable_name Value
query_cache_size 1048576
query_cache_type OFF
query_cache_limit 1048576
  • MySQL 8.0 输出示例:

结果为空(或报错:Unknown system variable 'query_cache_size')。

⚙️ 参数对比表

参数名 MySQL 5.7 MySQL 8.0 说明
query_cache_size ✅ 可配置缓存大小 ❌ 已删除
query_cache_type ✅ 可设置 ON/OFF/DEMAND ❌ 已删除
query_cache_limit ✅ 可配置单条结果上限 ❌ 已删除
Qcache_hits 等状态变量 ✅ 存在 ❌ 已删除

💡 二、为什么 MySQL 要移除 Query Cache?

  1. 严重的全局锁争用

    Query Cache 是一个全局共享内存区,任何写操作(INSERT/UPDATE/DELETE/DDL)都会锁住整个缓存区。

    在高并发下反而导致性能下降。

  2. 失效粒度粗

    任意表的修改都会使所有涉及该表的缓存失效。

    对更新频繁的表几乎命中率为零。

  3. 内存碎片严重,维护复杂

    大小不一的结果集插入会产生内存碎片,清理和整理耗时高。

👉 因此,MySQL 官方团队认为 "成本 > 收益",在 8.0 中彻底移除。


🧩 三、MySQL 查询执行架构概览

3.1 旧版(≤5.7)带 Query Cache 的逻辑

flowchart LR A[客户端] --> B[连接器] B --> C{查询缓存?} C -- 命中 --> R[直接返回结果] C -- 未命中 --> D[解析器/词法语法] D --> E[优化器/生成执行计划] E --> F[执行器/调用存储引擎] F --> P[(InnoDB 数据页/索引页)] F -->|结果| G[返回客户端] R --> G

3.2 MySQL 8.0 的真实执行链路(已无 Query Cache

flowchart LR A[客户端] --> B[连接器] B --> D[解析器/词法语法] D --> E[优化器/生成执行计划] E --> F[执行器/调用存储引擎] F --> P[(InnoDB Buffer Pool
页缓存/自适应哈希)] F --> G[返回客户端]

注:图中的 Buffer Pool 不是"查询结果缓存",它缓存的是数据页索引页


🧠 四、MySQL 5.7 的 Query Cache 工作原理(用于对比理解)

4.1 存储结构

  • Key:SQL 原文 + 当前数据库上下文。
  • Value:完整结果集。
  • 全局共享内存区:通过全局锁管理,容易碎片化。

4.2 执行流程

sequenceDiagram participant C as Client participant S as MySQL Server (<=5.7) C->>S: 发送 SQL S->>S: 检查 Query Cache alt 命中 S-->>C: 直接返回结果集 else 未命中 S->>S: 解析/优化/执行 S->>S: 将结果写入缓存 S-->>C: 返回结果 end

4.3 缓存失效机制

  • 任意表的更新操作都会使与该表有关的缓存条目全部失效。
  • 写多读少的表几乎无法命中缓存。

🔍 五、MySQL 8.0 中仍存在的"其他缓存机制"

类型 缓存内容 是否等价于 Query Cache
InnoDB Buffer Pool 数据页 / 索引页 ❌ 不是结果缓存
Prepared Statement Plan Cache 执行计划 ❌ 不缓存结果
Table Cache 已打开的表句柄
Metadata Cache 数据字典元信息

这些机制主要提升 I/O 与解析效率,并非存储"SQL 查询结果"。


🧮 六、如何在 MySQL 8.0 实现"查询缓存"效果

6.1 Cache-Aside 模式(推荐)

flowchart LR A[客户端] --> B[应用服务] B -->|查| C{Redis/Memcached} C -- 命中 --> R[直接返回结果] C -- 未命中 --> D[MySQL 8.0] D --> E[(InnoDB)] D -->|结果写入| C D --> R

6.2 缓存 Key 设计建议

  • 使用唯一主键或 SQL 指纹。
  • 可携带版本号:user:123:v27
  • 大结果集可分页存储。

6.3 缓存失效策略

  • TTL + 惰性删除:简单易行;
  • 精确失效:监听 Binlog / CDC(如 Debezium, Canal)更新缓存。

6.4 缓存伪代码

pseudo 复制代码
func getUserProfile(uid):
    key = "user:%d:v%d".format(uid, getVersion(uid))
    if cache.exists(key):
        return cache.get(key)
    row = mysql.query("SELECT * FROM user WHERE id=?", uid)
    cache.setex(key, ttl=600, value=row)
    return row

⚙️ 七、多级缓存执行链路

sequenceDiagram participant U as User participant A as 应用(L1本地缓存) participant R as Redis(L2) participant M as MySQL 8.0 U->>A: 查询 Q alt L1 命中 A-->>U: 返回 else L1 未命中 A->>R: GET key(Q) alt L2 命中 R-->>A: value A-->>U: 返回并写入L1 else L2 未命中 A->>M: 执行 Q M-->>A: 结果集 A->>R: SETEX key,value,ttl A-->>U: 返回并写入L1 end end

📈 八、性能观测与调优建议

  • Buffer Pool 命中率SHOW ENGINE INNODB STATUS
  • 慢查询分析EXPLAIN ANALYZE
  • 表缓存参数table_open_cachethread_cache_size
  • 应用层指标:缓存命中率、穿透、击穿、雪崩监控。

🧭 九、总结

结论 说明
✅ MySQL 8.0 移除查询缓存 所有相关参数与代码被删除
🔍 想要缓存结果 应在应用层或代理层实现
⚙️ 推荐架构 L1 本地缓存 + L2 Redis + MySQL
🚫 不再建议 使用数据库级"结果缓存"

一句话总结: 在 MySQL 8.0 里,"查询缓存"已成历史,但缓存思想永不过时。

真正的高性能来自于:架构分层 + 精确失效 + 多级缓存

相关推荐
SamDeepThinking6 小时前
MySQL 8 索引与 B+ 树-初浅理解
mysql
野犬寒鸦7 小时前
从零起步学习MySQL || 第七章:初识索引底层运用及性能优化(结合底层数据结构讲解)
java·数据库·后端·mysql·oracle
啊森要自信7 小时前
【MySQL 数据库】使用C语言操作MySQL
linux·c语言·开发语言·数据库·mysql
叫我龙翔10 小时前
【MySQL】从零开始了解数据库开发 --- 如何理解事务隔离性
数据库·mysql·数据库开发
苏小瀚1 天前
[MySQL] 索引
数据库·mysql
Warren981 天前
复习MySQL
数据库·windows·tcp/ip·mysql·ubuntu·ssh·ansible
凌~风1 天前
数据库原理实验报告:在ider里搭建mysql数据库
数据库·mysql·实验报告
2401_841495641 天前
【数据库开发】个人信息管理的数据库创建以及查询方法(最简单)
数据库·sql·mysql·sqlite·数据库开发·个人数据库·管理个人信息
lang201509281 天前
MySQL 8.0动态TLS配置全解析
mysql