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

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

相关推荐
蟹至之13 小时前
增删查改(其一) —— insert插入 与 select条件查询
数据库·mysql·增删查改
星光一影16 小时前
SpringBoot+Vue3无人机AI巡检系统
人工智能·spring boot·websocket·mysql·intellij-idea·mybatis·无人机
dessler16 小时前
MYSQL-主键(Primary Key)
linux·运维·mysql
dongchen。17 小时前
MySQL第四次作业
数据库·mysql
小白银子20 小时前
零基础从头教学Linux(Day 62)
数据库·mysql·oracle
Boilermaker19921 天前
【MySQL 进阶】高性能优化
数据库·sql·mysql
CoderOnly1 天前
SQL,CROSS JOIN速度优化
数据库·sql·mysql
老衲提灯找美女1 天前
MySQL的增删改查功能合集
数据库·mysql·增删改查·增删改查详细用法
Doro再努力1 天前
MySQL数据库07:分组查询与分类查询
数据库·mysql
弥生赞歌1 天前
Mysql作业四
数据库·mysql