mysql 8.0 彻底移除了 query cache,相关变量(如 query_cache_type)已从源码删除,配置即报错;应删除 my.cnf 中所有 query_cache_ 开头的行,并转向 innodb 缓冲池优化、应用层缓存及 sql 调优。

MySQL 8.0 中 Query Cache 不是“失效了”,而是彻底没了——你没法绕过它、调优它,更不能指望它缓解高并发读压力。必须换思路。
my.cnf 里还留着 query_cache_* 配置?立刻删掉
启动 MySQL 8.0 时出现 Unknown system variable 'query_cache_type',不是配置写错,是变量已被从源码中删除。哪怕只留一行 query_cache_size = 0,mysqld 就会拒绝启动。
- 打开
my.cnf或mysqld.cnf,搜索并删除所有以query_cache_开头的行(包括注释里的) - 别试图设成
OFF或0——这些值已无意义,MySQL 8.0 不识别它们 - 重启前用
mysqld --validate-config检查配置合法性,避免因残留项导致服务起不来
为什么高并发读接口反而变慢了?先看是不是缓存幻觉
升级后发现商品详情页响应变长,第一反应不是“缓存没了所以慢了”,而是确认:之前真靠 Query Cache 起效了吗?
- 执行
SHOW VARIABLES LIKE 'have_query_cache';—— 在 8.0+ 返回NO是正常;若在 5.7 环境返回YES,再查Qcache_hits和Com_select的比值,低于 0.05 基本等于没用 - Query Cache 对
SELECT * FROM goods WHERE id = ?这类带参数的语句根本无效——除非你手写固定值且空格/大小写完全一致 - 现代 ORM(如 Django ORM、MyBatis)默认走预处理语句,
PREPARE/EXECUTE路径压根不进 Query Cache,所谓“缓存收益”可能是误判
真正该调的不是 query_cache_size,而是 innodb_buffer_pool_size
InnoDB 缓冲池才是 8.0 下扛高并发读的核心资源,它缓的是数据页,不是结果集,复用率高、无全局锁、支持并发读。
- 设太小:Buffer pool hit rate 长期
- 设太大:挤占系统内存,触发 swap,反而拖慢整体响应;专用 DB 服务器建议设为物理内存的 50%~75%
- 检查是否生效:
SHOW STATUS LIKE 'Innodb_buffer_pool_read%';,计算Innodb_buffer_pool_read_requests / Innodb_buffer_pool_reads,比值 > 99% 才算健康 - 注意单位:
innodb_buffer_pool_size = 2G正确,= 2048就是 2048 字节——MySQL 不报错但实际无效
应用层缓存不是可选项,是必选项
MySQL 8.0 把缓存决策权交还给业务层。Redis 不是“加个缓存就完事”,得按查询特征分层处理:
- 配置类(
site_config)、维度类(regions)、聚合类(daily_order_count)适合直接存 Redis,key 明确、更新频次低、TTL 可控 - 单条记录查询(如
SELECT * FROM users WHERE id = 123)应转为user:123这样的 key,避免 SQL 拼接穿透 - 别缓整个
SELECT * FROM orders—— 结果集大、失效难、易击穿;改用覆盖索引 + Buffer Pool 更稳 - HTTP 层别漏掉:
Cache-Control: public, max-age=300让 CDN 或浏览器缓住静态化接口,减轻 DB 压力
最常被忽略的一点:Query Cache 的存在,曾让很多人把性能问题归因于“缓存没开好”,而忽略了 SQL 写法、索引缺失、Buffer Pool 不足这些真正要命的问题。现在它没了,那些问题浮出水面——不是变难了,是终于能对症下药了。











