mysql执行SQL时会缓存查询结果吗_mysql缓存机制解析

来源:这里教程网 时间:2026-02-28 20:51:59 作者:

MySQL 默认不缓存查询结果,除非你明确启用了查询缓存(Query Cache),而该功能在 MySQL 8.0 中已被彻底移除。

MySQL 8.0 之后没有 Query Cache

从 MySQL 8.0 开始,

query_cache_type
query_cache_size
等所有 Query Cache 相关变量和逻辑都被删除。执行
SHOW VARIABLES LIKE 'query_cache%'
将查不到任何结果;尝试设置
query_cache_type = 1
会报错
Unknown system variable 'query_cache_type'

这是官方明确的架构决策:Query Cache 在高并发写入场景下锁竞争严重,命中率低,反而拖慢整体性能 替代方案是依赖客户端缓存、应用层缓存(如 Redis)、或利用 InnoDB 的 Buffer Pool 缓存数据页(但不是 SQL 结果) 如果你刚升级到 8.0 并发现“缓存失效”,大概率是因为这个功能已不存在,而非配置没生效

InnoDB Buffer Pool 缓存的是数据页,不是查询结果

innodb_buffer_pool_size
控制的是内存中缓存的表数据和索引页(16KB 的 Page),不是 SELECT 语句返回的行集。这意味着:

相同
SELECT * FROM users WHERE id = 123
执行两次,第二次可能更快——但这是因为二级索引/主键页已在 Buffer Pool 中,无需磁盘 IO,不是“结果被缓存”
如果执行
SELECT COUNT(*) FROM huge_table
,Buffer Pool 对它帮助极小,因为要遍历大量页,且结果集本身不落缓存
Buffer Pool 不理解 SQL 语义:
SELECT name FROM users
SELECT email FROM users
即使走同一张表,也不会共享“结果”,只可能复用底层的数据页

哪些情况看起来像“SQL 被缓存”?

实际中常被误认为“MySQL 缓存了查询”的现象,通常来自以下原因:

OS page cache
:Linux 内核缓存了
.ibd
文件的读取页,重复查询物理文件读取变快,和 MySQL 无关
客户端驱动缓存:比如 Python 的
mysql-connector-python
默认不缓存,但某些 ORM(如 SQLAlchemy 启用
Cache
插件)或自定义连接池可能做结果缓存
代理层缓存:如 ProxySQL、MaxScale 配置了
query rules
做结果缓存,此时缓存发生在 MySQL 之前
查询计划复用(非结果):MySQL 会缓存执行计划(
EXPLAIN
输出结构),尤其对 Prepared Statement,但这不等于结果复用

想手动实现查询结果缓存,该怎么做?

MySQL 自身不提供安全可靠的查询结果缓存,必须由上层控制。常见做法:

对确定性查询(无
NOW()
RAND()
、用户变量等),在应用中用
SQL + 参数哈希值
作为 key,存入 Redis,设置合理 TTL
使用
SELECT ... INTO OUTFILE
+ 定时任务预热冷数据,但这属于离线缓存,不适用于实时场景
避免缓存大结果集:10MB 的
SELECT *
缓存反而增加序列化/网络开销,不如让 MySQL 每次计算
注意事务一致性:缓存的结果可能在其他事务提交后过期,需配合 binlog 位点或业务事件主动失效

真正容易被忽略的是:很多团队花时间调优

query_cache_size
,却没意识到自己用的是 MySQL 8.0 —— 先确认版本,再谈缓存。

相关推荐