mysql 8.0已彻底移除tmp_table_size参数,查它会报错或返回0;真正生效的是max_heap_table_size、internal_tmp_mem_storage_engine和temptable_max_ram(8.0.16+新增),且temptable_max_ram必须在配置文件中设置并重启生效。

MySQL 8.0 已完全移除 tmp_table_size 参数,查它只会报错或返回 0 —— 直接调这个参数根本无效。
确认 MySQL 版本和实际生效的临时表参数
先验证你真在用 8.0+:执行 SELECT VERSION();。若版本 ≥ 8.0.16,tmp_table_size 就是废参数,配置文件里留着会被静默忽略。
真正起作用的是这三个:
-
max_heap_table_size:仍控制内存临时表上限(也约束显式CREATE TEMPORARY TABLE ENGINE=MEMORY) -
internal_tmp_mem_storage_engine:默认为TempTable(比 MEMORY 更省、支持 BLOB),不建议改 -
temptable_max_ram:MySQL 8.0.16+ 新增,决定整个 TempTable 引擎可用内存池总量,默认为物理内存的 3%(上限 4 GiB)
必须查这三者:SELECT @@max_heap_table_size, @@internal_tmp_mem_storage_engine, @@temptable_max_ram;
快速判断是不是临时表在撑爆磁盘
别只看 / 分区满了就开调参。先定位源头:
- 查临时目录:
SELECT @@tmpdir;→ 然后df -h /path/to/tmpdir(注意:8.0+ 大量临时表默认走ibtmp1,不走@@tmpdir) - 查状态变量:
SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables';和Created_tmp_tables,比值 >15% 表示大量落盘 - 查 ibtmp1 占用:
ls -lh /var/lib/mysql/ibtmp1(路径以datadir为准),若 >10GB 且持续增长,基本就是它 - 用
lsof +D /var/lib/mysql看 mysqld 是否正往ibtmp1写大块数据
为什么改了 max_heap_table_size 还没用?
因为 temptable_max_ram 是总闸门,它不支持 SET GLOBAL,必须写进配置文件并重启才生效。常见错误:
- 只设了
max_heap_table_size = 256M,但漏配temptable_max_ram→ TempTable 引擎仍卡在默认 3% 限制下 - 写了
temptable_max_ram = 4G,但 MySQL 版本 G 解析失败,实际按 0 处理 - 改完没执行
SET GLOBAL innodb_fast_shutdown = 0; SHUTDOWN;→ 旧ibtmp1不释放,重启后继续膨胀
安全写法(my.cnf 的 [mysqld] 段):
max_heap_table_size = 268435456 temptable_max_ram = 4294967296 internal_tmp_mem_storage_engine = TempTable
比调参更关键的三件事
参数只是兜底。很多“落盘”根本不是内存不够,而是 SQL 写法触发了强制磁盘路径:
- 查询里含
TEXT、BLOB或超宽VARCHAR字段 → 无论参数多大,直接走磁盘临时表 -
GROUP BY或ORDER BY用了函数,如UPPER(name)、JSON_EXTRACT(data, '$.id')→ 无法利用索引,必建临时表 - 子查询结果参与外层
DISTINCT或UNION→ 中间集大,TempTable 内存池耗尽后立刻写ibtmp1
优先做:EXPLAIN FORMAT=TREE 看执行计划里哪一层标了 Using temporary;对涉及字段补联合索引,或把函数逻辑前置为生成列再索引。











