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

✅ 实验验证

你可以在终端中执行:

SHOW VARIABLES LIKE 'query_cache%';
  • MySQL 5.7 输出示例:
Variable_nameValue
query_cache_size1048576
query_cache_typeOFF
query_cache_limit1048576
  • MySQL 8.0 输出示例:

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

⚙️ 参数对比表

参数名MySQL 5.7MySQL 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 的逻辑

命中
未命中
结果
客户端
连接器
查询缓存?
直接返回结果
解析器/词法语法
优化器/生成执行计划
执行器/调用存储引擎
InnoDB 数据页/索引页
返回客户端

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

客户端
连接器
解析器/词法语法
优化器/生成执行计划
执行器/调用存储引擎
InnoDB Buffer Pool
页缓存/自适应哈希
返回客户端

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


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

4.1 存储结构

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

4.2 执行流程

Client MySQL Server (<=5.7) 发送 SQL 检查 Query Cache 直接返回结果集 解析/优化/执行 将结果写入缓存 返回结果 alt [命中] [未命中] Client MySQL Server (<=5.7)

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 模式(推荐)

命中
未命中
结果写入
客户端
应用服务
Redis/Memcached
直接返回结果
MySQL 8.0
InnoDB

6.2 缓存 Key 设计建议

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

6.3 缓存失效策略

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

6.4 缓存伪代码

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

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

User 应用(L1本地缓存) Redis(L2) MySQL 8.0 查询 Q 返回 GET key(Q) value 返回并写入L1 执行 Q 结果集 SETEX key,value,ttl 返回并写入L1 alt [L2 命中] [L2 未命中] alt [L1 命中] [L1 未命中] User 应用(L1本地缓存) Redis(L2) MySQL 8.0

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

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

🧭 九、总结

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

一句话总结:
在 MySQL 8.0 里,“查询缓存”已成历史,但缓存思想永不过时。
真正的高性能来自于:架构分层 + 精确失效 + 多级缓存

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值