MySQL查询缓存到底咋回事,原理和细节讲得挺透彻的分享
- 问答
- 2026-01-16 08:12:24
- 3
主要综合了早期MySQL官方文档、高性能MySQL书籍、以及像姜承尧、何登成等数据库领域专家的技术博客和分享中的核心观点)
说起MySQL的查询缓存,这玩意儿在MySQL 5.7及更早的版本里,是个让人又爱又恨的功能,爱它是因为,当它真的起作用时,效果立竿见影,能把一个复杂的查询速度提升几个数量级,恨它是因为,它太容易成为性能瓶颈,而且管理起来非常麻烦,所以在MySQL 8.0里直接被官方给移除了,但理解它为啥被移除,对我们怎么写好SQL语句、怎么设计数据库,非常有帮助。
查询缓存是个啥?简单比喻
你可以把它想象成一个超级简单的“字典”或者“备忘录”,每当MySQL收到一条SELECT语句,它不会立刻去翻书查数据,而是先看看这个“备忘录”。
它的工作流程大概是这样的:

- 拿到一条SELECT语句。
- 对这条语句进行一个哈希计算,生成一个唯一的“指纹”(也就是哈希值),注意,这里哪怕你的SQL语句只是大小写不同,或者多个空格,生成的“指纹”都会不一样,就会被当成两条不同的查询。
- 拿着这个“指纹”去“备忘录”(查询缓存)里找,看有没有之前记录下来的结果。
- 如果找到了,并且有权限访问这些数据,那就太好了!直接把这个“标准答案”返回给客户端,根本不用去麻烦存储引擎(比如InnoDB)去磁盘上找数据了,这一步叫做“缓存命中”。
- 如果没找到,那就只能老老实实地去执行查询,等拿到结果后,如果满足条件,MySQL会把这个结果和当初的查询“指纹”一起,存到“备忘录”里,方便下次再用。
查询缓存工作的关键细节和“苛刻”条件
为啥说它“苛刻”呢?因为它判断两个查询是否相同的规则非常死板。
- 一字不差:查询语句必须完全一样,包括大小写、空格、注释。
SELECT * FROM t和select * from t会被认为是两条不同的查询,不会共用缓存。 - 不能有不确定函数:查询里如果包含了像
NOW()、CURRENT_DATE()、RAND()这样的函数,因为每次执行结果都可能不同,所以这条查询的结果是不会被缓存的,同理,用了用户自定义变量或者系统变量的查询,也基本不会被缓存。 - 查询涉及的表必须有读取权限:这个好理解,你都不能读这个表,自然不能缓存它的结果。
缓存何时失效?这是最大的痛点!
这才是查询缓存最核心也最让人头疼的地方,它的失效策略非常“粗粒度”。

想象一下,你的“备忘录”里记录了很多问题的答案,问题的源头数据发生了一点点变化,比如你只是往用户表里插入了一条新用户记录,或者修改了某条商品的价格,这时会发生什么?
MySQL的处理方式是:把这个用户表相关的所有“备忘录”条目,全部撕掉!
是的,你没看错,是全部,不管你的缓存结果是来自于一个查询一亿条数据的复杂报表SQL,还是一个只是简单查询表里有多少行数据的 SELECT COUNT(*),只要这个表发生了任何写操作(INSERT、UPDATE、DELETE、TRUNCATE,甚至某些ALTER TABLE),那么所有和这个表有一丁点关系的查询缓存,都会被清空。
这就带来了几个严重问题:

- 写操作成本剧增:一个本来很快的UPDATE语句,除了要更新数据,还要额外承担清理庞大查询缓存的工作,在高并发的写环境下,这会给数据库带来巨大的压力,经常出现的情况是,你辛辛苦苦把结果缓存起来,还没被读几次,就被一个写请求给清空了,缓存命中率极低,反而得不偿失。
- “锁”竞争:MySQL需要保证在查询缓存的时候,不会有其他线程来修改缓存的内容,所以它有一个查询缓存锁,当有大量并发查询和写入时,这个锁会成为激烈的争用点,导致系统瓶颈,姜承尧在他的文章里多次提到,在高并发场景下,查询缓存的内置锁竞争是导致性能急剧下降的主要原因之一。
为啥最终被MySQL 8.0抛弃了?
正是因为上述这些固有的缺陷,尤其是对写性能的拖累和粗粒度的失效机制,使得查询缓存在现代高并发、高写入的应用中弊大于利,官方团队认为,与其保留一个效率不高且难以优化的功能,不如直接移除,从而简化代码结构,减少潜在的锁竞争,让用户去寻求更优的解决方案。
给我们的启示
虽然查询缓存本身已经“退役”了,但它的兴衰给了我们很多宝贵的经验:
- 不要过度依赖数据库层面的透明缓存:对于复杂的、读多写少的热点数据,更好的办法是在应用层(比如使用Redis、Memcached)做一层独立的缓存,这样缓存的生命周期可以由应用逻辑精确控制,失效策略更灵活,也不会影响数据库本身的写入性能。
- SQL语句规范化很重要:即使没有查询缓存,养成编写统一、规范SQL的习惯(比如统一大小写、空格),也有利于应用层缓存和数据库本身对重复查询的优化。
- 理解“任何设计都有权衡”:查询缓存的初衷是好的,但它的实现没有跟上时代的发展,这提醒我们,在选择技术方案时,一定要结合自己的业务场景(是读多写少还是写多读少?并发量多大?),充分了解其优缺点,而不是盲目开启默认配置。
MySQL查询缓存是一个特定历史时期下的产物,它简单直接地解决了“重复读”的问题,但其僵化的机制无法适应复杂的现代应用场景,它的故事是一个关于技术权衡和演进的经典案例。
本文由邝冷亦于2026-01-16发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://waw.haoid.cn/wenda/81679.html
