mysql 8.0中myisam表加载变慢的根本原因是内核放弃优化其元数据访问路径,每次information_schema查询都可能触发隐式open table操作,且系统表已全转innodb,遗留myisam表被“冷处理”。

MyISAM表在MySQL 8.0中加载变慢的根本原因
这不是配置没调好,而是MySQL 8.0彻底放弃了对MyISAM元数据访问路径的优化。5.7时代,information_schema查表时大量依赖缓存且跳过状态校验;8.0默认每次查询都可能触发隐式OPEN TABLE操作,尤其当MyISAM表数量多、混在InnoDB库中时,开销会指数级放大。
更关键的是:MySQL 8.0已将所有系统表(如mysql.user、mysql.db)强制转为InnoDB,但业务层遗留的MyISAM表不会自动迁移——它们成了被内核“冷处理”的异类。
为什么不能只改information_schema_stats_expiry
设SET SESSION information_schema_stats_expiry = 86400能缓解查询延迟,但治标不治本:
- 该参数只影响
information_schema元数据缓存有效期,不影响MyISAM表本身的打开/扫描逻辑 - MyISAM无事务、无行锁,8.0对其文件锁管理更保守,高并发下
MyISAM table is full或Waiting for table flush错误频发 - 一旦执行
ANALYZE TABLE或REPAIR TABLE,仍会卡住整个连接线程
必须执行的MyISAM转InnoDB操作
别犹豫,直接批量转换。以下命令在升级前或升级后立即执行(需停写或低峰期):
SELECT CONCAT('ALTER TABLE `', table_schema, '`.`', table_name, '` ENGINE=InnoDB;')
FROM information_schema.tables
WHERE engine = 'MyISAM' AND table_schema NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys');
执行生成的SQL后注意三点:
- 确认
ROW_FORMAT=DYNAMIC已生效:SHOW CREATE TABLE tbl_name里必须含ROW_FORMAT=DYNAMIC,否则utf8mb4索引可能建失败 - 检查
innodb_file_per_table=ON(8.0默认开启),避免转换后所有表挤进ibdata1导致无法收缩 - 转换后运行
mysql_upgrade --skip-sys-schema,防止因系统表引擎不一致引发权限异常
系统表空间配置陷阱:别碰ibdata1扩容
升级后若发现ibdata1暴涨,大概率是漏关innodb_file_per_table或误删了独立表空间文件。正确做法是:
- 确保
[mysqld]段中明确设置innodb_file_per_table=ON(8.0默认值,但老配置可能覆盖) - 禁用
innodb_data_file_path的手动配置——除非你真要管理共享表空间,否则留空即可 - 不要尝试用
ALTER DATABASE ... UPGRADE DATA DIRECTORY去“优化”MyISAM残留目录,该命令仅适用于NDB引擎
真正需要关注的是转换后的.ibd文件归属权和SELinux上下文(Linux下常见Operation not permitted就因此而起),而非共享表空间本身。











