mysql 8.0 彻底删除查询缓存模块,query_cache_type等所有相关变量已从源码中移除,配置即报错、启动失败;必须清除my.cnf中所有query_cache_开头的配置项,并转向innodb缓冲池优化、应用层缓存等替代方案。

MySQL 8.0 不是“关闭”查询缓存,而是从代码层面彻底删除了它——query_cache_type、query_cache_size、query_cache_limit 全部不存在了,配置即报错,启动直接失败。
MySQL 8.0 启动报 Unknown system variable 'query_cache_type' 怎么办
这不是配置写错了,是变量本身被物理移除。MySQL 8.0.3 起,所有 query_cache_* 变量已从源码中清空,任何残留配置都会导致 mysqld 拒绝启动。
- 必须手动删掉
my.cnf或my.ini中所有以query_cache_开头的行,一个都不能留 - 云数据库(如 RDS)若使用自定义参数组,也要同步清理,否则升级后服务起不来
- 别试图设成
0或OFF—— 它已经不是开关,是“没这个东西”
为什么 SELECT 查询要抢同一个全局锁
查询缓存底层是一个单点全局哈希表,所有操作(查是否存在、写入结果、清空条目)都必须先获取 LOCK_query_cache。哪怕只是检查 SELECT * FROM users WHERE id = 123 是否命中,也得排队等这把锁。
- 多核服务器上,几十个并发 SELECT 会卡在锁等待,
%systemCPU 升高,SHOW PROCESSLIST显示大量Waiting for query cache lock - 这个锁和 InnoDB 行锁完全不兼容,无法分片、无法降级,是硬编码死结
- UPDATE 一次,清空整张表缓存的过程本身也要持锁,进一步延长阻塞时间
UPDATE 一次就让整张表缓存全失效,合理吗
不合理,但这就是它的行为:失效粒度是表级的,且不区分影响范围。只要对 users 表执行任意 DML,所有命中该表的缓存(不管 SQL 多具体、结果集多小)全部丢弃。
-
UPDATE users SET name='a' WHERE id=1和UPDATE users SET updated_at=NOW()在缓存层面待遇完全一样 - 预处理语句(
PREPARE/EXECUTE)默认绕过查询缓存,而现代 ORM 几乎全走这条路 - 含
NOW()、RAND()、用户变量、临时表的查询直接被跳过,实际能进缓存的 SQL 极少
缓存命中率长期低于 5%,为什么还要留着
字节级匹配是硬伤:SELECT id FROM t WHERE x=1 和 SELECT id FROM t WHERE x = 1 就是两个 key;加个注释、换行、大小写不同,全 miss。真实业务里带用户 ID、分页 offset、时间戳的查询,几乎每条都是新 SQL。
- 实测多数生产环境
Qcache_hits / Com_select长期低于0.1,意味着 10 次查询不到 1 次命中 - 但开销始终在线:每次 SELECT 都要走一遍缓存判断逻辑,内存碎片整理(
FLUSH QUERY CACHE)还吃 CPU - 这部分内存不归
innodb_buffer_pool_size管,无法复用,纯属额外占用
真正容易被忽略的是:Query Cache 的存在,会让问题排查跑偏——看到命中率低,第一反应是“调大缓存”,而不是意识到它本就不该存在。MySQL 8.0 把这块逻辑砍掉,腾出的资源全给了更可控的 innodb_buffer_pool_size、应用层缓存和 SQL 优化空间。











