mysql 8.4升级后查询变慢主因是统计信息失真、innodb_file_per_table配置异常或索引失效;需优先验证innodb_tablestats是否过期、检查innodb_file_per_table是否为on、改用alter table force替代optimize table,并调低long_query_time至1.0秒捕获亚慢查询。

MySQL 8.4升级后查询变慢,大概率不是引擎本身退化,而是统计信息失真、配置默认值变更或索引失效导致的误判——别急着调参或重建表,先验证这三点。
查 INNODB_TABLESTATS 是否崩了
升级后 INFORMATION_SCHEMA.INNODB_TABLESTATS 可能未自动刷新,导致优化器基于过期的 avg_row_length 和 data_length 做出错误执行计划(比如该走索引却选了全表扫描)。
- 执行
SELECT (data_length + index_length) / table_rows AS avg_row_size FROM INFORMATION_SCHEMA.TABLES WHERE table_name = 't' AND table_schema = 'db',和你实际单行字节数对比:若偏差超 3 倍(如算出来 2.3KB,实际才 180 字节),说明统计已失效 - 强制更新统计:
ANALYZE TABLE t;(对大表加WAIT 30防锁) - 检查慢查询日志里是否频繁出现
Using temporary; Using filesort且rows远大于filtered * rows——这是统计失真最典型的副作用
确认 innodb_file_per_table 是否为 ON
MySQL 8.4 默认启用 innodb_file_per_table,但升级过程可能因配置继承或 dump 导入不完整导致它被重置为 OFF。一旦是 OFF,所有表共享 ibdata1,后续任何 OPTIMIZE TABLE 或 ALTER TABLE ... FORCE 都无法释放物理空间,Data_free 也不代表可回收。
- 运行
SHOW VARIABLES LIKE 'innodb_file_per_table';,必须返回ON - 如果是
OFF,不能在线改:需先导出数据(mysqldump --single-transaction)、停库、修改配置、重建实例再导入 - 翻一翻升级前的备份 dump 文件开头,看是否有
SET GLOBAL innodb_file_per_table=ON——没有就说明旧环境长期关着它,升级后更易出问题
用 ALTER TABLE FORCE 替代 OPTIMIZE TABLE
OPTIMIZE TABLE 在 MySQL 8.4 仍默认走 ALGORITHM=COPY,全程阻塞写入;而 ALTER TABLE t FORCE 会触发 online DDL,只在最后短暂加 MDL 写锁,更适合生产环境。
- 对大表务必加
WAIT 30:ALTER TABLE t FORCE, WAIT 30;,避免被长事务卡死 - 执行前查活跃事务:
SELECT * FROM information_schema.INNODB_TRX WHERE trx_started ,有就等它结束 - 磁盘空间必须 ≥
Data_length + Index_length(查SHOW TABLE STATUS LIKE 't'),因为重建过程先写新.ibd文件,再原子替换
真正容易被忽略的是:升级后 long_query_time 仍是默认 10 秒,大量耗时 1~3 秒的“亚慢查询”根本不会进日志——务必先设成 1.0 并打开 log_queries_not_using_indexes(配合 min_examined_row_limit=1000),否则你连问题 SQL 都抓不到。











