MySQL 8.0 彻底移除查询缓存,性能下降主因是旧配置失效、PERSIST机制覆盖my.cnf、统计信息过期及optimizer_switch默认值变更,需重点调优innodb_buffer_pool_size、ANALYZE TABLE和optimizer_switch参数。

MySQL 8.0 确实彻底删掉了 query_cache_type 和 query_cache_size,配置即报错、服务启动失败——这不是“没生效”,是代码里真没了。性能下降不是因为缓存没了,而是旧配置失效 + 新默认值不匹配 + 优化器重新评估数据时踩了坑。
检查 persisted_variables 是否覆盖了你的 my.cnf 配置
MySQL 8.0 的 PERSIST 机制会把 SET PERSIST 写入的变量存进 mysqld-auto.cnf,且优先级高于 my.cnf。升级前若有人执行过 SET PERSIST sort_buffer_size = 64K,你改了 my.cnf 也白搭。
- 查当前生效值:
SELECT * FROM performance_schema.persisted_variables; - 看加载顺序:
SELECT VARIABLE_NAME, VARIABLE_SOURCE, VARIABLE_PATH FROM performance_schema.variables_info WHERE VARIABLE_SOURCE IN ('PERSISTED', 'CONFIG'); - 临时清空(慎用):
RESET PERSIST;,再重启验证
强制刷新统计信息,否则优化器“瞎猜”
5.7 升 8.0 后,INNODB_TABLESTATS 表里的 last_update 时间仍停留在升级前,导致 EXPLAIN 显示的 rows 严重失真——比如实际 100 行,它以为有 10 万行,于是放弃索引走 type: ALL。
- 查失真程度:
SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESTATS WHERE TABLE_NAME = 'your_table';,对比SHOW INDEX FROM your_table中的Cardinality和SELECT COUNT(DISTINCT your_col) FROM your_table - 立刻修复:
ANALYZE TABLE your_table;(对慢查询涉及的所有表都执行) - 长期建议:设
innodb_stats_persistent = ON,避免后续频繁失效
对比 optimizer_switch 默认值变化,别让优化器“绕开”你的索引
8.0 至少有 12 项 optimizer_switch 子开关默认值变了,比如 mrr=off(5.7 是 on)、index_merge=on(8.0 默认开启,但常导致优化器拼凑单列索引,反而比复合索引还慢)。
- 导出 baseline:
SELECT @@optimizer_switch;(升级前务必存档) - 升级后比对差异,重点关注带
=off的项,如mrr、use_index_extensions、derived_merge - 临时验证:
SET SESSION optimizer_switch='mrr=on,use_index_extensions=on';,再跑EXPLAIN看是否恢复原执行路径 - 若
Extra出现Using intersect()或Using union(),说明index_merge在捣乱,可先SET SESSION optimizer_switch='index_merge=off';试试
别再调 query_cache,重点盯紧 innodb_buffer_pool_size 和排序缓冲
innodb_buffer_pool_size 是 8.0 下最直接影响 QPS 的单一参数。它不仅要缓数据和索引,还要分一部分给元数据(字典表、DDL 日志等),沿用 5.7 的 1G 设置,在 8.0 下可能只剩 800MB 可用。
- 查真实占用:
SELECT * FROM performance_schema.memory_summary_global_by_event_name WHERE event_name LIKE 'memory%dictionary%'; - 设值必须对齐 1MB:
innodb_buffer_pool_size = 5G可以,4800M会被静默忽略 - 排序相关参数更敏感:8.0 废弃
max_length_for_sort_data,统一走内存排序,sort_buffer_size不够就必然filesort。别盲目加到 4M——100 并发就是 400MB,容易被系统 kill - 验证是否生效:
mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';",值必须和配置文件里写的完全一致
真正容易被忽略的是:QPS 提升的上限,取决于单次查询的最小 I/O 成本,而不是缓存命中率;而这个成本,在 8.0 下由 innodb_buffer_pool_size、索引设计、统计信息准确性共同决定——不是靠关掉或打开某个“缓存开关”能绕过去的。



















