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

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

相关推荐
Fleshy数模12 小时前
CentOS7 安装配置 MySQL5.7 完整教程(本地虚拟机学习版)
linux·mysql·centos
az44yao13 小时前
mysql 创建事件 每天17点执行一个存储过程
mysql
秦老师Q14 小时前
php入门教程(超详细,一篇就够了!!!)
开发语言·mysql·php·db
橘子1315 小时前
MySQL用户管理(十三)
数据库·mysql
Dxy123931021615 小时前
MySQL如何加唯一索引
android·数据库·mysql
我真的是大笨蛋15 小时前
深度解析InnoDB如何保障Buffer与磁盘数据一致性
java·数据库·sql·mysql·性能优化
怣5015 小时前
MySQL数据检索入门:从零开始学SELECT查询
数据库·mysql
人道领域15 小时前
javaWeb从入门到进阶(SpringBoot事务管理及AOP)
java·数据库·mysql
千寻技术帮16 小时前
10404_基于Web的校园网络安全防御系统
网络·mysql·安全·web安全·springboot
spencer_tseng17 小时前
MySQL table backup
mysql