mysql 8.0移除查询缓存因其在高并发下引发全局锁竞争、缓存命中率低、维护开销大,反而制约性能;取而代之的是应用层缓存、innodb buffer pool优化及sql调优等更高效、可扩展的方案。

MySQL 8.0 删除查询缓存(Query Cache)不是“功能退化”,而是明确放弃一个在真实高并发写场景下会拖垮性能的模块——它在写操作稍有频率时,就从加速器变成刹车片。
query_cache_type=1 时,一次 UPDATE 就能锁住所有 SELECT
开启查询缓存后,任何对表的 INSERT、UPDATE 或 DELETE 操作,都会触发全局锁(Query Cache Lock),强制清空该表关联的所有缓存条目。这个锁是排他的、跨会话的,且无法降级或分片。
- 即使只更新一行,
user表所有缓存的SELECT * FROM user WHERE id = ?全部失效 - 此时所有正在检查缓存的读请求必须排队等待该锁释放,QPS 断崖下跌
- 在 OLTP 场景中,
Qcache_hits / (Qcache_hits + Qcache_inserts)常低于 2%,但锁开销照常发生
缓存命中条件苛刻到几乎不可用
缓存只对字节级完全一致的 SELECT 生效:空格、注释、大小写、客户端字符集、SQL mode 差一点,就完全不命中。现代应用基本绕过它:
- ORM(如 MyBatis、Hibernate)生成的 SQL 带动态参数占位符,每次语句文本都不同
- 预处理语句(
PREPARE+EXECUTE)根本不会进入查询缓存路径 - 含
NOW()、RAND()、用户变量、临时表的查询直接被跳过 - 分区表默认禁用查询缓存,而生产环境大量使用分区
内存碎片 + 全局管理开销远超收益
query_cache_size 设得越大,碎片越严重;设得小,又频繁淘汰。MySQL 不提供 LRU 或 TTL 等可控策略,只靠固定块大小(query_cache_min_res_unit)硬切,导致:
- 缓存结果集为 1KB,却分配 4KB 块,内存浪费明显
-
FLUSH QUERY CACHE整理碎片时需获取全局锁,期间所有查询阻塞 - 每个查询都要做哈希计算 + 全局内存查找,CPU 开销随并发线程数线性上升
- 实测显示:开启缓存后,相同负载下 CPU usage 升高 13%~18%
真正关键的一点是:查询缓存的失效粒度和 InnoDB 的 MVCC 机制冲突——它保证的是“语句级强一致性”,但代价是牺牲所有并发可扩展性。MySQL 8.0 把这块逻辑彻底剥离,把资源让给 innodb_buffer_pool_size 和更精细的 Performance Schema 监控,反而让读写吞吐更稳、更可预期。











