mysql 5.7将内部临时表默认引擎从myisam改为innodb,提升崩溃安全性、并发性能和i/o可控性,但要求优化缺失索引的低效查询。

MySQL 5.7 默认用 InnoDB 做内部临时表,5.6 用的是 MyISAM
这是最直接影响复杂查询性能的底层变化。MySQL 在执行 GROUP BY、ORDER BY、子查询、窗口函数(5.7 虽未原生支持但部分优化路径已铺垫)等操作时,若内存不足,会把中间结果写入磁盘临时表。5.6 中这个临时表默认引擎是 MyISAM,而 5.7 改为 InnoDB。
关键区别在于:MyISAM 不支持事务、无行级锁、崩溃后易损坏、且在高并发写临时结果时容易成为瓶颈;InnoDB 则天然支持 MVCC、行锁、崩溃安全,并能复用已有 buffer pool 和刷盘策略。尤其当多个连接同时触发大排序或聚合时,5.7 的临时表 I/O 更可控、锁冲突更少。
tmp_table_size 和 max_heap_table_size 仍控制内存阈值,但引擎切换让“溢出”代价更低
这两个参数在 5.6 和 5.7 中行为一致:只要单个临时表所需内存 ≤ min(tmp_table_size, max_heap_table_size),就走内存临时表(MEMORY 引擎);超限则落盘。但 5.6 落盘用 MyISAM,5.7 落盘用 InnoDB。
- MyISAM 落盘临时表需额外建.frm + .MYD + .MYI 文件,初始化开销大,且不支持压缩页
- InnoDB 落盘临时表复用
innodb_temp_data_file_path配置的共享临时表空间(如ibtmp1),预分配、可动态扩展、支持压缩与加密 - 即使落盘,5.7 的临时表也能参与
innodb_buffer_pool缓存,而 MyISAM 临时表完全绕过 BP
升级后临时表行为突变,可能暴露旧 SQL 的隐性问题
你不会看到报错,但某些在 5.6 上“凑合跑”的语句,在 5.7 上可能突然变慢甚至夯住——尤其是那些本该加索引却靠暴力排序撑过去的 GROUP BY 查询。因为 InnoDB 临时表对磁盘 I/O 模式更敏感,且不支持 MyISAM 那种简单粗暴的“全表扫描+文件排序”路径。
典型现象包括:
-
Creating sort index状态持续时间变长(SHOW PROCESSLIST可见) - 磁盘
ibtmp1文件暴涨,且INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO显示大量活跃临时表 - 慢日志里出现原本不慢的语句,
EXPLAIN显示Using temporary; Using filesort,但实际执行耗时翻倍
这时不是回退引擎,而是要检查 SQL 是否缺失排序字段索引,或是否能改写为覆盖索引扫描。
不建议手动切回 MyISAM 临时表,internal_tmp_disk_storage_engine 是危险开关
5.7.7+ 提供了 internal_tmp_disk_storage_engine 参数,可设为 MyISAM 或 InnoDB。但强行设回 MyISAM 会丢失崩溃恢复能力,且与 GTID、并行复制等 5.7 核心特性存在兼容风险。
真正该调的参数是:
- 增大
tmp_table_size和max_heap_table_size(需同步设,且不超过innodb_buffer_pool_size的 20%) - 确认
innodb_temp_data_file_path所在磁盘有足够空间和 IOPS(它默认自动扩展,但首次扩展会阻塞) - 监控
Created_tmp_disk_tables状态变量,若该值占比 > 5%,说明大量查询被迫落盘,应优先优化 SQL
临时表引擎的切换不是“加速开关”,而是把压力从文件系统推到了 InnoDB 子系统——它要求你正视那些长期被 MyISAM 宽容掩盖的低效查询。











