MySQL 8.0 彻底删除 query_cache_type 等所有查询缓存变量,配置即报错;须删除 my.cnf 中所有 query_cache_ 开头的行并重启 mysqld,改用 InnoDB 缓冲池优化、索引调优及应用层缓存。

MySQL 8.0 启动时报 Unknown system variable 'query_cache_type' 怎么办
这不是配置写错了,是变量本身已被删除。MySQL 8.0 彻底移除了所有 query_cache 相关变量——query_cache_type、query_cache_size、query_cache_limit 全都不再识别。你往 my.cnf 里写它们,MySQL 启动时直接报错退出,不会忽略或静默降级。
常见错误现象:
- 服务无法启动,日志里明确出现
Unknown system variable 'query_cache_type' - 从 5.7 升级到 8.0 后,原配置未清理,导致迁移失败
解决方法很简单:删掉配置文件中所有以 query_cache_ 开头的行。别试图设成 0 或 OFF,它已经不存在了。
为什么 SELECT 查询要抢同一个全局锁
查询缓存底层是一个全局哈希表,所有读写操作都必须先获取 LOCK_query_cache。哪怕只是检查一句 SELECT * FROM users WHERE id = 123 在不在缓存里,也得排队等这个锁。
在多核服务器上,几十个并发查询一上来就卡在锁上,CPU 花在等锁的时间比执行 SQL 还多。更糟的是,这个锁和 InnoDB 的行锁、表锁完全不在一个量级——它是单点瓶颈,无法水平扩展。
影响场景:
- 高并发只读接口(如商品详情页)反而因缓存锁变慢
- CPU
%system指标异常升高,top显示大量线程处于S(sleeping)但实际在锁等待 -
SHOW PROCESSLIST中出现大量Waiting for query cache lock
UPDATE 一次就清空整张表所有缓存,合理吗
不合理,但这就是它的行为。只要对某张表执行任意写操作(INSERT/UPDATE/DELETE/ALTER),这张表关联的所有缓存条目全部失效,且清空过程本身也要持锁。
这意味着:
- 哪怕只改一行数据,
users表下所有缓存(比如SELECT name FROM users WHERE id=1、SELECT * FROM users LIMIT 10)全被扔掉 - 缓存刚建好,可能下一秒就被清空,变成“临时工式缓存”
- 写越频繁,缓存命中率越低;实测多数生产环境
Qcache_hits/Com_select长期低于 0.1
分区表甚至默认禁用查询缓存——而大表分区已是标配,这说明设计已与主流用法脱节。
缓存命中率低到不如不缓,关键原因是什么
核心是字节级匹配:SQL 文本差一个空格、换行、注释、大小写、参数值,就视为不同查询。例如:
SELECT id FROM t WHERE x=1 SELECT id FROM t WHERE x = 1 SELECT /* v1.2 */ id FROM t WHERE x=1
这三条在查询缓存里是三个 key,互不共享。现代应用几乎全走预处理语句(PREPARE/EXECUTE),而预处理语句根本绕过查询缓存。
真实业务中,带用户 ID、时间戳、分页 offset 的接口,每条 SQL 都是新面孔。缓存不仅没省事,还额外消耗 CPU 做哈希计算、内存管理、碎片整理——官方测试显示,未命中查询会多花约 13% 资源。
真正该关注的,是 innodb_buffer_pool_size 是否设为物理内存的 50%~75%,以及索引是否覆盖高频查询。查询缓存的消失,不是功能倒退,而是把资源让给更可靠、可伸缩的机制。











