MySQL 5.7及更早版本query_cache基本失效,8.0已移除;因其缓存粒度粗、失效频繁、高并发下锁争用严重,命中率低且拖慢性能,应禁用并转向InnoDB缓冲池与应用层缓存优化。

MySQL 5.7 及更早版本中,query_cache 已基本失效;8.0 版本直接移除——别再为它调优了。
为什么 query_cache 在高并发下反而拖慢查询
它的缓存粒度是整条 SQL 文本(含空格、大小写、注释),只要有一个字符不同,就视为新查询;且任何对相关表的 INSERT/UPDATE/DELETE 都会让所有命中该表的缓存条目失效。在写多读少或表更新频繁的场景下,缓存命中率极低,而失效锁开销却很高。
常见错误现象:SHOW STATUS LIKE 'Qcache%' 显示 Qcache_hits 极低、Qcache_lowmem_prunes 持续增长、Qcache_inserts 远高于 Qcache_hits。
- 启用
query_cache_type = 1后,单条SELECT带SQL_NO_CACHE才能绕过,但业务代码几乎不会加 -
query_cache_size设得越大,内存碎片和锁争用越严重,尤其在多核机器上 - MyISAM 表的缓存效率略高于 InnoDB,但 InnoDB 是默认引擎,这点优势无实际意义
哪些场景曾“看似适合”但实际要避开
静态配置表、报表后台的只读从库、低频管理查询——这些听起来合理,但现实里往往不成立。
- 所谓“静态表”常因运维操作(如
ANALYZE TABLE)或监控脚本触发隐式更新,清空全部缓存 - 从库开启
query_cache后,主库一个BINLOG事件可能引发从库多次缓存失效(因 relay log 应用顺序与主库不完全一致) - 即使
SELECT完全相同,若客户端连接使用了不同字符集(如utf8mb4vsutf8),缓存也不共享
替代方案:用好 InnoDB 缓冲池和客户端缓存
InnoDB 的 innodb_buffer_pool_size 才是真正影响热数据读取速度的核心。它缓存的是数据页和索引页,复用率高、无 SQL 文本匹配开销,且与写操作协同良好。
- 把
innodb_buffer_pool_size设为物理内存的 50%–75%(专用 DB 服务器),比调query_cache_size有效十倍 - 对确定不变的结果(如国家列表),改用应用层缓存(Redis / Memcached),由业务控制过期逻辑
- 对带参数的查询(如
SELECT * FROM user WHERE id = ?),准备好的语句(PREPARE)+ 连接池复用,比依赖 query cache 更稳定 - 确认是否真需要加速读:先查
SHOW ENGINE INNODB STATUS中的 buffer pool hit rate,低于 95% 才值得优化
现在 MySQL 的查询加速,关键不在“记下上次结果”,而在“让下次读更快地拿到数据页”。query_cache 的设计思路早已被 InnoDB 的现代缓存机制覆盖,强行启用只会掩盖真实瓶颈。











