事情本身不复杂,线索都在日志里。DBA 在 MySQL 5.7 上跑一个报表 SQL,执行到一半报 ERROR 1114 (HY000): The table '/tmp/#sql_2f1a_0' is full,同机器的应用日志也跟着报 No space left on device,df 里 /tmp 已经 100%。
第一反应是「/tmp 用的 tmpfs,大小只有内存的一半,一写就满」,验证下来不成立。
这类报错背后常见的原因有几处,逐个排除就行。tmp_table_size 和 max_heap_table_size 太小,临时表很快就落盘。少数情况下是查询里带了 GROUP BY 和大字段,磁盘临时表撑爆了 /tmp。
还有一种情况,没有索引导致全表扫描,中间结果集比原表还大。
第一件事是看磁盘临时表的使用量
mysql -e 'SHOW GLOBAL STATUS' | grep -i created_tmp
接着确认临时表上限和 tmpdir
mysql -e 'SHOW VARIABLES' | grep -E 'tmpdir|tmp_table_size'
给大查询补上可用的索引并复核计划
mysql -e 'EXPLAIN SELECT id FROM orders WHERE user_id = 1'
等前面都确认过,再清掉残留临时文件并观察磁盘
du -sh /tmp/* 2>/dev/null | sort -h | tail
怎么算真的好了,看的是同一批现象。同样的报表 SQL 能跑完,Created_tmp_disk_tables 增量明显下降,/tmp 使用率回到 20% 以下。
tmpdir 指向 tmpfs 时表会吃掉内存,大查询多的实例把 tmpdir 挪到独立数据盘更稳;清 /tmp 前先确认没有其他进程在用。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
