mysql 8.0 彻底移除了查询缓存,query_cache_type 等参数变为只读且无效,源码中相关逻辑已删除;其被弃用主因是全局锁、缓存失效频繁、sql 字符串敏感及事务隔离问题,替代方案包括 innodb buffer pool、应用层 redis 缓存、proxysql 等。

MySQL 查询缓存已被移除,query_cache_type 在 8.0 中无效
MySQL 8.0 版本起,官方彻底移除了查询缓存(Query Cache)功能。如果你在 8.0+ 环境中看到 query_cache_type、query_cache_size 等配置项,它们已变成只读变量,设置无效,且启动时会警告「unknown variable」。这不是配置没生效,而是代码层已删除——连源码里相关逻辑都删干净了。
所以,别再查“如何开启 MySQL 查询缓存”了,它不存在于当前主流版本中。
为什么 MySQL 彻底砍掉查询缓存?
查询缓存在 5.7 及更早版本中就饱受诟病,核心问题不是“能不能用”,而是“用了反而拖慢”。它在以下场景下表现极差:
- 只要表有任意写操作(
INSERT/UPDATE/DELETE),该表所有缓存结果立即失效,锁住整个缓存模块做清理 - 缓存键是完整 SQL 字符串(区分大小写、空格、注释),
SELECT * FROM t和SELECT * FROM t(末尾多空格)被视为两条不同查询 - 无法感知事务隔离级别变化,可能返回脏数据或过期快照
- 全局锁竞争严重,高并发下成为性能瓶颈,尤其在 OLTP 场景中
这些缺陷导致绝大多数生产环境早就通过 query_cache_type = 0 主动关闭它。MySQL 团队最终选择一刀切除,把资源投入到更可控的缓存方案上(如 InnoDB Buffer Pool、客户端缓存、代理层缓存)。
Android使用SQLite数据库进行开发的教程,chm格式,SQLite 是一款非常流行的嵌入式数据库,它支持 SQL 查询,并且只用很少的内存。Android 在运行时集成了 SQLite,所以每个 Android 应用程序都可以使用 SQLite 数据库。对数熟悉 SQL 的开发人员来时,使用 SQLite 相当简单。可以,由于 JDBC 不适合手机这种内存受限设备,所以 Android 开发人员需要学习新的 API 来使用 SQLite。本文主要讲解 SQLite 在 Android 环境中的基
替代方案:哪些地方还能“缓存查询结果”?
虽然服务端查询缓存没了,但实际开发中仍有多个有效缓存层级可选,关键看你的访问模式和一致性要求:
-
InnoDB Buffer Pool:缓存的是数据页(
.ibd文件内容),不是 SQL 结果。对重复读同一行/范围的查询非常高效,由innodb_buffer_pool_size控制大小 -
应用层缓存:用 Redis 或 Memcached 缓存
SELECT的完整结果(JSON/序列化对象),自己控制 key 生效逻辑与失效时机 - 连接层/代理缓存:如 ProxySQL 支持基于 SQL 模板的缓存(支持参数化匹配),比原生 Query Cache 更灵活、无全局锁
-
客户端缓存:某些驱动(如 MySQL Connector/J)提供
cachePrepStmts=true缓存预编译语句结构,不缓存结果,但减少解析开销
注意:SELECT SQL_CACHE ... 这类语法在 8.0 中仍能解析(向后兼容),但完全不触发任何缓存行为,仅当作普通 SQL 执行。
验证你是否误以为“缓存还在工作”
常见错觉来源:执行两次相同 SELECT,第二次响应飞快,就以为是查询缓存生效。其实更可能是:
- InnoDB Buffer Pool 已加载对应数据页,磁盘 I/O 消失
- 操作系统 Page Cache 缓存了文件系统块(尤其是小表)
- 客户端或中间件做了本地缓存(比如 ORM 的 identity map 或 query cache)
- MySQL 正在执行计划缓存(
prepared_statement_cache),但那是解析树缓存,非结果缓存
想确认是否真有“结果级缓存”,最直接方式是关掉所有外部缓存,重启 MySQL(清空 Buffer Pool),用 FLUSH TABLES 和 RESET QUERY CACHE(5.7 下有效)对比前后耗时——但在 8.0 上,后者命令会报错 ERROR 1286 (42000): Unknown table 'QUERY CACHE',这就是最硬的证据。









