mysql 8.0 彻底删除查询缓存模块,query_cache_type等参数已从代码中移除,配置即报错且服务无法启动,必须彻底删除my.cnf中所有query_cache_开头的行。

MySQL 8.0 不是“关掉了查询缓存”,而是从代码里彻底删掉了 query_cache_type、query_cache_size、query_cache_limit 等所有相关逻辑——配置文件里写任何 query_cache_* 都会导致 mysqld 启动失败,报错 Unknown system variable 'query_cache_type'。
MySQL 8.0 启动报 Unknown system variable 'query_cache_type' 怎么办
这不是配置写错了,是变量本身已不存在。MySQL 8.0.3 起,整个 Query Cache 模块被物理移除,解析器连识别都做不到。
- 必须手动删除
my.cnf(或my.ini)中所有以query_cache_开头的行,一个都不能留 - Percona Server 8.x、MariaDB 10.6+ 同样不兼容,别指望降级兼容
- Docker 或云数据库(如 RDS)若使用自定义参数组,也要同步清理残留项
- 升级前没清理?服务根本起不来,错误日志末尾通常就是这句报错
为什么 SELECT 查询总卡在 Waiting for query cache lock
因为 Query Cache 底层用的是单点全局锁 LOCK_query_cache,所有读写操作(查、存、清)都得抢它。
- 哪怕只是检查
SELECT * FROM users WHERE id = 123在不在缓存里,也得排队等锁 - 多核服务器上,几十个并发 SELECT 会集中阻塞在锁上,
CPU %system异常升高 -
SHOW PROCESSLIST里大量线程显示Waiting for query cache lock,就是典型征兆 - 这个锁和 InnoDB 行锁完全不在一个量级——无法分片、不能降级、不可绕过
为什么 UPDATE 一行就让整张表的缓存全失效
Query Cache 的失效粒度是表级(table-level),不是语句级或行级,且清空过程本身还要持锁。
-
UPDATE users SET name='x' WHERE id=1一执行,所有命中users表的缓存(不管 SQL 多具体)立刻被扔掉 - 缓存刚建好,下一秒就被清空,变成“临时工式缓存”
- 事务未提交时缓存已失效,但新查询又不能读未提交数据,出现“失效了却还不能用”的真空
- 分区表默认禁用查询缓存,而生产环境大表基本都分区——说明设计早已脱离实际
为什么缓存命中率长期低于 5% 却还在消耗资源
命中条件苛刻到近乎不可用:SQL 必须字节级一致,且大量常见语句直接被跳过。
-
SELECT id FROM t WHERE x=1和SELECT id FROM t WHERE x = 1是两个 key(空格差一点就不行) - 预处理语句(
PREPARE/EXECUTE)、含NOW()、RAND()、用户变量、子查询、视图的查询,一律不进缓存路径 - 命中率低不是偶然:实测
Qcache_hits / Com_select普遍低于 0.1,但每次 SELECT 仍要走哈希计算 + 全局内存查找 - 内存管理反成负担:
query_cache_size是静态大块分配,碎片严重时FLUSH QUERY CACHE自身就吃 CPU
最易被忽略的一点:Query Cache 的“缓存结果”和 InnoDB 的 MVCC 机制本质冲突——它用全局锁换语句级强一致性,代价是牺牲全部并发可扩展性。删掉它,资源才真正回到 innodb_buffer_pool_size、索引覆盖、自适应哈希这些更可控、更高复用率的优化路径上。











