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 里,"查询缓存"已成历史,但缓存思想永不过时。

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

相关推荐
Zzzzmo_1 天前
【MySQL】JDBC(含settings.xml文件配置/配置国内镜像以及pom.xml文件修改)
数据库·mysql
FirstFrost --sy1 天前
MySQL内置函数
数据库·mysql
eggwyw1 天前
MySQL-练习-数据汇总-CASE WHEN
数据库·mysql
mygljx1 天前
MySQL 数据库连接池爆满问题排查与解决
android·数据库·mysql
Bdygsl1 天前
MySQL(1)—— 基本概念和操作
数据库·mysql
身如柳絮随风扬1 天前
什么是左匹配规则?
数据库·sql·mysql
jiankeljx1 天前
mysql之如何获知版本
数据库·mysql
小李来了!1 天前
数据库DDL、DML、DQL、DCL详解
数据库·mysql
我科绝伦(Huanhuan Zhou)2 天前
【生产案例】MySQL InnoDB 数据损坏崩溃修复
数据库·mysql·adb
海棠蚀omo2 天前
从零敲开 MySQL 的大门:库与表的基础操作实战(保姆级入门指南)
数据库·mysql