mysql 8.0.16+ 升级后 ibtmp1 疯涨导致磁盘爆满,主因是 temptable 引擎启用后超内存临时结果直接写入 ibtmp1 而非 tmpdir;需修改配置文件中 temptable_max_ram(不支持运行时设置),并同步调大且等值设置 tmp_table_size 和 max_heap_table_size,同时优化 sql 避免 using temporary 落盘。

MySQL 8.0.16+ 升级后 ibtmp1 疯涨,不是 tmpdir 满了
升级后磁盘爆满却查不到 /tmp 或 /var/tmp 写满痕迹?大概率是 ibtmp1 在撑爆磁盘——这是 InnoDB 临时表空间文件,MySQL 8.0.16+ 默认启用 TEMPTABLE 引擎后,超内存的临时结果直接写这里,不走 @@tmpdir。
常见误判点:
- 只调
tmp_table_size,没动temptable_max_ram,参数完全无效 -
SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables'飙升,但lsof +D /tmp查不到大文件 - 错误日志里报
The table '/tmp/#sql-xxx' is full,实际路径是误导,真实落盘位置是ibtmp1
必须改 temptable_max_ram,且不能 SET GLOBAL
temptable_max_ram 是 TEMPTABLE 引擎的总内存池上限,默认值是物理内存的 3%(上限 4 GiB),对报表类查询极容易卡死。它不支持运行时修改,必须写进配置文件。
实操建议:
- 先查当前值:
SELECT @@temptable_max_ram;(返回字节数,比如 2147483648 = 2 GiB) - 在
/etc/my.cnf的[mysqld]段添加:temptable_max_ram = 4G(注意:MySQL 8.0.23+ 才完全支持G单位,旧版本建议写4294967296) - 若物理内存 ≥ 128 GiB,可设为
6G,但别超物理内存 15%,否则可能触发系统 OOM - 重启前执行:
SET GLOBAL innodb_fast_shutdown = 0;,再SHUTDOWN;,确保旧ibtmp1可被安全重建
tmp_table_size 和 max_heap_table_size 还得同步调
哪怕你已经调了 temptable_max_ram,老式 MEMORY 临时表逻辑依然存在——比如某些 GROUP BY、ORDER BY 场景仍会走 MEMORY 引擎,这时就又回到“双参数取小值”的老问题。
关键点:
-
tmp_table_size和max_heap_table_size必须显式设成完全相等,例如都设为256M - 重启后验证:
SELECT @@tmp_table_size, @@max_heap_table_size;,两个值必须一致且单位是字节 - 混跑 OLTP + 报表的实例,建议上限 ≤ 物理内存的 20%,比如 64 GiB 机器最多设
12G,但要注意并发连接数乘上该值后的总内存占用
SQL 写法才是根因,参数只是兜底
再大的 temptable_max_ram 和 tmp_table_size,也拦不住硬伤 SQL。EXPLAIN 出现 Using temporary 且没走索引,基本等于主动申请落盘。
高频踩坑点:
-
GROUP BY JSON_EXTRACT(data, '$.id')或ORDER BY UPPER(name):函数表达式无法利用索引,强制建临时表 -
SELECT *+ORDER BY created_at:只要表含TEXT或长VARCHAR字段,TEMPTABLE 引擎会因行格式限制直接落盘 - 视图定义含
GROUP BY或UNION,且外层没加LIMIT:执行计划里select_type = DERIVED+rows接近全表,说明全量物化已发生
真正要盯住的不是磁盘用了多少,而是 Created_tmp_disk_tables / Created_tmp_tables 比值是否持续 >10%——这个数字一高,说明优化器已经在反复放弃内存路径,光调参只是把爆炸时间往后推几小时而已。











