MySQL 8.0 彻底移除了查询缓存(Query Cache),包括系统变量、配置项、源码模块及SQL语法支持;官方不提供且无法安全实现等效功能,应改用Redis、物化视图、InnoDB缓冲池优化或HTTP缓存等替代方案。

MySQL 8.0 中 query_cache_type 根本不存在
不是配错,是没得配。执行 SHOW VARIABLES LIKE 'query_cache%' 在 MySQL 8.0+ 中一定返回空结果;若配置文件里还留着 query_cache_type = 1,启动时会报警告:[Warning] 'query_cache_type' is deprecated and will be removed...;更关键的是,源码里整个模块已被删除——连变量注册逻辑都没了,插件也无法绕过这个事实。
别试 Query Cache 插件:官方不提供,社区无可靠实现
MySQL 8.0 没有、也不会提供「启用查询缓存」的官方插件。第三方尝试模拟 query cache 的 UDF 或代理层方案(如早期 ProxySQL 的简单缓存)都面临同样问题:无法安全处理事务可见性、MVCC 快照一致性、表结构变更通知等底层语义。你手动加的“缓存层”大概率在 READ-COMMITTED 隔离级别下返回过期结果,或在主从延迟时把从库脏数据缓存出去。
- 所有声称“支持 MySQL 8.0 查询缓存”的开源代理/中间件,实际都是应用层缓存封装,和原生 query cache 无关
- 用
SELECT SQL_CACHE会直接报错:ERROR 1286 (42000): Unknown table engine 'QUERY CACHE' - 试图用
init_connect+ 自定义函数拦截 SQL 并缓存?语法解析不可靠,且无法感知隐式 DDL(如 ALTER TABLE … RENAME COLUMN)
真正可用的替代方案按场景拆解
缓存不是目的,降低重复查询延迟才是。与其强求“SQL 级缓存”,不如匹配真实读写模式选对工具:
-
热维表(城市、状态码、配置项):用 Redis 的
SETEX config:app:features 3600 {...},键名带版本号,更新时主动DEL,比数据库自己猜“要不要缓存”靠谱得多 -
聚合类慢查询(日活、销售额统计):建物化表
CREATE TABLE daily_summary AS SELECT ... FROM logs WHERE dt = CURDATE() - INTERVAL 1 DAY,定时任务每小时刷新,应用查这张表 -
高频单行读(用户资料、订单详情):InnoDB 缓冲池必须调够——
innodb_buffer_pool_size设为物理内存的 60%~75%,再配合覆盖索引(如SELECT id, name, email FROM users WHERE id = ?加索引(id, name, email)),99% 场景下比任何外部缓存更快更稳 -
HTTP API 层:在 Nginx 或网关加
Cache-Control: public, max-age=300,让 CDN 或客户端缓存响应,数据库根本不用参与
最容易被忽略的性能陷阱
很多人升级到 MySQL 8.0 后还在日志里搜 Qcache_hits,或盯着慢查询日志里“没走缓存”的提示发愁——但真正拖慢重复查询的,从来不是“少了 query cache”,而是:innodb_buffer_pool_size 还卡在默认的 128MB、关键字段没建索引、查询里写了 SELECT * 导致回表、或者用了 JSON_CONTAINS() 这类无法走索引的函数。先跑一遍 EXPLAIN FORMAT=TREE 看执行计划,再检查缓冲池命中率(SHOW STATUS LIKE 'Innodb_buffer_pool_read%'),比折腾缓存插件实在得多。


















