MySQL报错“Disk full”实为/tmp或/var/lib/mysql所在分区满,需先系统层df查空间;临时文件#sql-*残留不删则磁盘不释放,应find定位并安全删除;改tmpdir至大空间分区并调低buffer大小、建索引优化才是根本解法。

MySQL报错“Disk full while writing to file”时,90%不是MySQL配置错了,而是/tmp或/var/lib/mysql所在分区真满了——先别进MySQL,直接切系统层查df。
为什么Writing to net或Copying to tmp table其实是磁盘写不进去
这两个状态看着像网络或查询慢,实际是MySQL在往tmpdir落盘时被操作系统拒绝(Errcode: 28)。常见于大排序、GROUP BY、CREATE TABLE AS SELECT等操作,临时文件生成后不自动清理,尤其当/tmp是tmpfs(内存挂载)时,几GB就爆满。
-
SELECT @@tmpdir, @@innodb_tmpdir;查真实路径,多数指向/tmp,但df -h /tmp可能显示100%,而df -h /还剩20%——别被假象骗 - 临时文件名通常是
#sql-*或ibtmp1,用sudo find /tmp -user mysql -name "#sql*" -ls能快速定位 - 如果
/tmp是tmpfs,df -h显示的大小受限于RAM,不是磁盘空间,df -i反而更关键(小文件多易耗尽inode)
紧急清理tmpdir里残留的#sql-*临时文件
这些文件是MySQL崩溃、查询中断或kill线程后遗留的,不删掉,磁盘就一直被占着。不能靠重启自动清——MySQL不负责回收。
- 先确认归属:
sudo find /tmp -user mysql -name "#sql*" -mmin +5 -ls(只列5分钟前创建的) - 安全删除:
sudo find /tmp -user mysql -name "#sql*" -mmin +5 -delete - 如果
find报“Permission denied”,加2>/dev/null过滤错误;若仍删不掉,说明文件正被mysqld进程占用,需lsof -p $(pgrep mysqld) | grep /tmp确认后kill -9对应线程 - 删完立刻
df -h /tmp验证,别信“删了就释放”的直觉——有时文件被进程持有,lsof | grep deleted能看到“deleted”标记的大文件
改tmpdir到有空间的分区并限制缓冲区大小
临时清理只是救火,不改配置,下次一样爆。重点不是增大tmpdir,而是让MySQL少往磁盘写临时文件。
- 新建目录并授权:
sudo mkdir -p /data/mysql-tmp && sudo chown mysql:mysql /data/mysql-tmp - 在
my.cnf的[mysqld]段加:tmpdir = /data/mysql-tmp,然后sudo systemctl restart mysql - 同步调低
sort_buffer_size和join_buffer_size(比如从2G降到4M),避免单个查询吃光tmpdir - 对常跑
ORDER BY或GROUP BY的大表,在对应字段建索引,能直接绕过磁盘临时表
最常被忽略的是:tmpdir改完必须验证SELECT @@tmpdir是否生效,且/data/mysql-tmp目录得有足够inode——否则df -h看着有空间,df -i一查又是100%,照样报错。

















