改了innodb_temp_data_file_path仍涨到上百gb,是因为该参数仅控制新实例启动时的初始大小和上限,对已存在的膨胀ibtmp1文件完全无效;必须先执行set global innodb_fast_shutdown = 0、确认无长事务、flush tables,再完整重启才能清理旧文件并生效新配置。

为什么改了 innodb_temp_data_file_path 还是涨到上百 GB
这个参数只在 MySQL 启动时生效,用于定义新 ibtmp1 文件的初始大小和上限(比如 ibtmp1:12M:autoextend:max:5G),但对已存在的膨胀文件完全无效。旧的 ibtmp1 会一直保留,哪怕你删光所有临时表、杀掉所有连接,文件体积也不会缩小——InnoDB 不支持在线收缩临时表空间。
重启前必须做的三件事,缺一不可
直接 systemctl restart mysqld 可能导致启动失败或数据异常:
- 执行
SET GLOBAL innodb_fast_shutdown = 0(需 SUPER 权限,且实例不能为只读) - 确认无长事务残留:
SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 60 - 手动刷脏页:
FLUSH TABLES,减少 shutdown 过程中未落盘的缓冲区压力
tmp_table_size 和 max_heap_table_size 必须设成一样
MySQL 判断是否用内存临时表,取的是这两个值中的较小者。如果只调大 tmp_table_size 到 512M,而 max_heap_table_size 还是默认 16M,那实际阈值仍是 16M,一超就全落盘写进 ibtmp1 或系统 /tmp,反而加速磁盘打满。
推荐设置(根据内存余量调整,不建议超过 128M):
SET PERSIST tmp_table_size = 67108864; SET PERSIST max_heap_table_size = 67108864;
注意:5.7.20+ 才支持 SET PERSIST 持久化;低版本需写入配置文件并重启。
哪些 SQL 最容易把 ibtmp1 写爆
不是所有 GROUP BY 都危险,关键看执行计划和数据特征:
-
EXPLAIN显示Using temporary+Using filesort,且结果集大 -
GROUP BY字段无索引,或用了函数(如GROUP BY DATE(created_at)) -
DISTINCT多字段 + 含VARCHAR(2000)或TEXT列 -
UNION(非UNION ALL)去重,且关联列无索引支撑
真正管用的操作顺序是:先查 SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables' 看落盘频率,再结合 performance_schema.events_statements_summary_by_digest 定位高消耗 SQL,最后才调参——否则等于给堵车路口加宽车道却不疏解车流。











