MySQL 8.0 默认使用TempTable引擎,但需显式配置temptable_max_ram等参数并重启生效,否则易因参数不匹配或未验证版本(≥8.0.13)而回退MEMORY,导致更高频落盘。

MySQL 8.0 默认已用 TempTable 引擎,但多数人没配对参数,结果比 MEMORY 还容易落盘。
确认 internal_tmp_mem_storage_engine 是否真在用 TempTable
别只信“默认值”,得查运行时实际值。旧配置残留或版本低于 8.0.13 都会导致 fallback 到 MEMORY:
- 执行
SELECT @@internal_tmp_mem_storage_engine;—— 返回TempTable才算生效 - 执行
SELECT VERSION();—— 必须 ≥8.0.13,否则TempTable不可用 - 若返回
MEMORY,说明配置未加载、my.cnf 没写对位置,或 MySQL 启动时忽略该行(比如写在 [client] 段)
temptable_max_ram 是真正决定是否落盘的开关
tmp_table_size 和 max_heap_table_size 在 MySQL 8.0 中已不直接控制内存临时表大小;temptable_max_ram 才是 TempTable 引擎的内存池上限。超了就往 ibtmp1 写,不是 /tmp:
- 查当前值:
SELECT @@temptable_max_ram;(单位字节) - 默认是物理内存的 3%,64 GiB 机器约 2 GiB —— 报表类查询轻松突破
- 必须在 my.cnf 的
[mysqld]段显式设置,例如:temptable_max_ram = 4G(注意:8.0.23 前不支持4096M写法) - 设太高有风险:超过物理内存 15% 可能触发系统 OOM,尤其容器环境
tmp_table_size 和 max_heap_table_size 要设等值且 ≤ temptable_max_ram
这两个参数虽不直接限制 TempTable 大小,但影响其初始内存分配策略。设错会人为制造瓶颈:
- 必须设成相同值,例如:
tmp_table_size = 256M且max_heap_table_size = 256M - 若二者不等,MySQL 取小值作为阈值;若该小值 >
temptable_max_ram,TempTable 仍会立即分页落盘 - 升级后若配置里还留着
tmp_table_size却没删max_heap_table_size,后者可能仍是默认 16M,导致实际生效上限只有 16M
别忽略 SQL 本身才是根本瓶颈
调参只能缓解,不能替代索引优化。EXPLAIN 出现 Using temporary,本质是索引没覆盖查询路径:
- GROUP BY 字段无索引?建联合索引,顺序要匹配最左前缀
- ORDER BY 表达式如
UPPER(name)或JSON_EXTRACT(data, '$.id')?建函数索引 - SELECT * + GROUP BY?改成只选必要字段,避免 TEXT/VARCHAR(2000) 强制触发 off-page 存储
- 监控比值:
Created_tmp_disk_tables / Created_tmp_tables> 5% 就该查慢日志,而不是继续加内存
TempTable 的优势在于按需分页落盘、支持 BLOB、节省 30%~50% 内存,但它不会自动修复低效 SQL。最容易被忽略的是:调完 temptable_max_ram 后没重启 MySQL,或者忘了 innodb_fast_shutdown = 0 就直接关机,导致旧 ibtmp1 文件无法清理,磁盘持续告警。


















