mysql临时表路径由tmpdir变量控制,需通过修改my.cnf中[mysqld]段的tmpdir参数并重启mysqld生效;必须确保目录属主为mysql、权限正确、非nfs/fuse、selinux标签适配,且不能动态修改。

不是磁盘满就清 /tmp,错误根源在 MySQL 实际使用的 tmpdir 路径及其所在文件系统空间是否耗尽——且已删除的临时文件不重启 MySQL 不会释放空间。
查清 MySQL 真正在用的 tmpdir 路径
别凭经验猜是 /tmp,MySQL 启动时可能 fallback 到 /var/tmp、/run/mysqld,或容器里一个只有 1GB 的 volume。执行:
mysql -e "SHOW VARIABLES LIKE 'tmpdir';"
输出的值才是真实路径。常见陷阱包括:
-
tmpdir指向/var/lib/mysql-tmp,而该目录挂载在 tmpfs 或小容量 overlayfs 上 - Docker 中 host 映射路径(如
/host/mysql-tmp)已 100%,但df -h /显示根分区还有空间 - 某些 systemd 发行版默认让 mysqld 使用
/run/mysqld,而/run是内存文件系统,大小受限
确认对应挂载点是否真满了,且有被“占着不放”的文件
先定位挂载点:
df -h $(dirname $(mysql -Nse "SELECT @@tmpdir"))
如果 Use% 达到 100%,再检查是否有已删除但进程仍持有的文件:
lsof | grep -i 'deleted' | grep mysql
若看到类似 /var/lib/mysql-tmp/#sql-ib12345 (deleted) 的条目,说明空间没真正回收。此时:
- 最稳妥:执行
systemctl restart mysqld(或service mysql restart) - 生产环境无法重启时,可尝试
KILL长事务连接,但成功率低,且新查询仍可能触发相同问题 - 切勿只
rm -rf目录内容后就认为搞定——句柄不释放,空间照旧不可用
安全清理或迁移 tmpdir 目录
能清则清,但必须分清哪些文件真属于 MySQL 临时表:
- 可清理:文件名含
#sql-、SQL_、MYD_(前提是无活跃查询依赖) - 不能碰:
ibtmp1、aria_log.、mysql.sock、慢日志、binlog —— 它们不属于临时表范畴 - 改配置前必须停服务:
systemctl stop mysqld - 新路径需满足:
chown mysql:mysql /new/tmpdir、chmod 750 /new/tmpdir、文件系统为 ext4/xfs(避免 NFS/overlayfs) - 修改
/etc/my.cnf的[mysqld]段:tmpdir = /mnt/big-disk/mysql-tmp,然后重启
tmpdir 不支持动态修改,硬改配置也不生效的典型原因
SET GLOBAL tmpdir = '/new/path' 会直接报错:Variable 'tmpdir' is a read only variable。常见误操作包括:
- 只改了 my.cnf 却没重启 mysqld,MySQL 仍在用旧路径启动
- 新路径权限不对(如属主不是
mysql),MySQL 启动失败并 fallback 到默认路径 - 配置中写成
tmp_dir或tempdir,拼写错误导致参数被忽略 - 使用了冒号分隔多个路径(
tmpdir = /a:/b:/c),但第一个路径所在挂载点已满,MySQL 不会自动轮到下一个
最容易被忽略的一点:tmpdir 影响的不只是 CREATE TEMPORARY TABLE,排序、JOIN、子查询、ALTER TABLE 都可能生成大临时文件——所以即使业务没显式建临时表,磁盘爆满照样报错 28。











