ibtmp1膨胀由活跃长事务及高磁盘临时表SQL驱动,需通过INFORMATION_SCHEMA.INNODB_TRX查超60秒事务,结合performance_schema.events_statements_summary_by_digest定位SUM_CREATED_TMP_DISK_TABLES高的语句,并用EXPLAIN验证Using temporary/Using filesort,同时确保tmp_table_size与max_heap_table_size设为相同值以避免过早落盘。

查清当前哪些事务在写临时表空间
临时表空间(ibtmp1)膨胀不是凭空发生的,它一定由正在运行的事务驱动。先确认有没有长事务在持续占用临时资源:
执行 SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 60;,结果非空就说明存在活跃超时事务。
重点看 trx_rows_modified 和 trx_state 字段:若状态是 RUNNING 且修改行数巨大,大概率就是它在往 ibtmp1 写排序/分组中间结果。
别只盯着 processlist——有些事务不执行 SQL 但持有锁、没提交,照样让 InnoDB 保留临时段不释放。
定位触发临时表的SQL语句
光知道有长事务不够,得锁定具体哪条 SQL 在“造数据”:
用 performance_schema.events_statements_summary_by_digest 查高消耗语句:SELECT DIGEST_TEXT, COUNT_STAR, SUM_CREATED_TMP_TABLES, SUM_CREATED_TMP_DISK_TABLES FROM performance_schema.events_statements_summary_by_digest WHERE SUM_CREATED_TMP_DISK_TABLES > 100 ORDER BY SUM_CREATED_TMP_DISK_TABLES DESC LIMIT 5;
再结合 EXPLAIN FORMAT=TREE 或 EXPLAIN ANALYZE 看执行计划里是否含 Using temporary + Using filesort;
特别注意三类高危模式:GROUP BY DATE(created_at)(函数导致索引失效)、UNION(非 ALL)、多表 JOIN 无关联条件(笛卡尔积);
如果 @@tmpdir 指向 /tmp 且该分区是 tmpfs,哪怕 ibtmp1 没爆,也会因 inode 耗尽或内存上限报 The table is full。
检查 tmp_table_size 和 max_heap_table_size 是否同步
这两个参数决定内存临时表能撑多大,但 MySQL 实际取两者中的较小值:
执行 SELECT @@tmp_table_size, @@max_heap_table_size;,若数值不等(比如前者是 64M,后者是 16M),那阈值就是 16M,一超就落盘到 ibtmp1 或系统 tmpdir;
线上建议设为相同值,例如 SET PERSIST tmp_table_size = 67108864; 和 SET PERSIST max_heap_table_size = 67108864;(MySQL 5.7.20+ 支持);
注意:设太大(如 >512M)可能引发单查询吃光内存,被 OOM Killer 杀掉进程;
设太小(Created_tmp_disk_tables 会飙升,直接推高 ibtmp1 写入量。
重启前必须完成的清理动作
想靠重启回收 ibtmp1 空间,但跳过清理步骤会导致旧文件残留、启动失败:
先执行 SET GLOBAL innodb_fast_shutdown = 0;(需 SUPER 权限,且实例不能只读);
再确认无长事务(重复查 INNODB_TRX);
然后手动刷盘:FLUSH TABLES;,减少 shutdown 阶段缓冲区压力;
Linux 下杀完 mysqld 后务必 lsof | grep ibtmp1,确保文件未被进程占用;Windows 下用 taskkill /f /t /im mysqld.exe 彻底清空;
删掉旧 ibtmp1 后首次启动,MySQL 会按 innodb_temp_data_file_path 定义重建,无需手动 touch 或 chown。
重启本身不解决问题,真正起效的是重启前那几步——尤其是 innodb_fast_shutdown = 0 和彻底终止 mysqld 进程。很多人卡在“删了文件重启还是 955G”,其实只是旧文件被某个残留线程锁着没删干净。


















