MySQL 8.0 中 query_cache_type 等变量已被源码物理删除,非禁用而是彻底不存在;必须手动清除 my.cnf 中所有 query_cache_ 开头的行(含注释),否则启动报错退出,并应转向 InnoDB 缓冲池调优、应用层缓存等替代方案。

MySQL 8.0 中 query_cache_type 等变量已被物理删除,不是“关了”,是根本不存在——配置即报错、启动即失败。别试图保留或绕过,必须清理+转向替代机制。
my.cnf 里还留着 query_cache_* 就起不来服务
MySQL 8.0.3 起,query_cache_type、query_cache_size、query_cache_limit 全部从源码中移除。mysqld 启动时解析配置,遇到不认识的变量直接报 Unknown system variable 'query_cache_type' 并退出。
- 必须手动删掉
my.cnf(或my.ini)中所有以query_cache_开头的行,包括注释掉的(如# query_cache_type = 0)也得清干净 - Docker 镜像、RDS 参数组、Percona Server 8.x 同样不识别,不存在“设为 0 就能兼容”的可能
- 验证方式:启动前执行
mysqld --validate-config,比靠日志翻找更直接 -
SELECT SQL_CACHE在 8.0 中会报语法错误:ERROR 1286 (42000): Unknown table engine 'QUERY CACHE',连解析都过不去
别再调 query_cache,重点盯紧 innodb_buffer_pool_size
Query Cache 缓存的是结果集,有全局锁、表级失效、字节级匹配等硬伤;而 innodb_buffer_pool_size 缓存的是数据页,支持 MVCC、LRU-K 淘汰、无全局锁,是现在唯一需要认真调优的核心缓存开关。
- 中低端服务器建议设为物理内存的 50%–75%,例如 2GB 总内存可设
innodb_buffer_pool_size = 1G(注意单位!不能只写1024) - 验证是否生效:
SHOW STATUS LIKE 'Innodb_buffer_pool_read%',计算Innodb_buffer_pool_read_requests / Innodb_buffer_pool_reads,比值 > 99% 才算健康 - 升级后若 QPS 明显下跌,可能是缓冲池冷启动:检查
innodb_buffer_pool_dump_at_shutdown是否为ON,路径权限是否正常;可手动触发SET GLOBAL innodb_buffer_pool_load_now = ON
JDBC 连接失败报 query_cache_size 错误?其实是驱动没升级
旧版 JDBC 驱动(如 com.mysql.jdbc.Driver)在握手阶段会主动探测 query_cache_size 等变量,而 8.0 已不响应——结果不是连接超时,而是直接报 Unknown system variable 'query_cache_size'。
- 驱动类名必须换成
com.mysql.cj.jdbc.Driver - Maven 实际加载的必须是
mysql-connector-java-8.0.33+,而非残留的 5.x 版本 - Spring Boot 项目要检查是否显式排除了
spring-boot-starter-jdbc,导致降级使用旧驱动 - 连接 URL 需补全
?serverTimezone=UTC&allowPublicKeyRetrieval=true&useSSL=false等 8.0 强制参数,否则握手失败日志可能被误判为缓存变量问题
应用层缓存才是 Query Cache 的合理继承者
官方不提供、也无法安全实现等效插件——任何试图在 MySQL 外部模拟 Query Cache 的方案,都绕不开事务可见性、MVCC 快照一致性、主从延迟等底层语义问题。
- 对读多写少的热维表(城市、状态码、配置项),用 Redis 缓存完整结果集,TTL 设为 30 分钟到几小时,更新时主动
DELkey - 对强一致性要求的查询(如用户余额),跳过缓存直连 DB,或采用写后失效策略:
UPDATE user SET balance = ? WHERE id = ?后立刻DEL redis:key:balance:{uid} - 避免缓存含
NOW()、RAND()、用户变量(@var)、预处理语句的动态 SQL——这类本来就不该进缓存 - ProxySQL 是最接近原生行为的现成方案,但需注意它不分析语义,
SELECT FOR UPDATE或含变量的语句缓存后可能返回错误结果
真正难的不是“怎么缓存”,而是判断哪些查询值得缓、缓多久、失效时机是否可控——这些在 Query Cache 时代由 MySQL 硬编码决定,在 8.0 之后,交还给了业务逻辑本身。


















