tmpdir空间满时排序失败的典型现象是查询卡在copying to tmp table或报错“the table '#sql-xxxx' is full”“os error code 28”,根本原因是mysql在tmpdir落盘临时文件时磁盘写满;需先执行select @@tmpdir;和df -h确认实际路径及空间,再动态set global tmpdir切换并同步调大tmp_table_size与max_heap_table_size。

tmpdir空间满时排序失败的典型现象
执行 ORDER BY、GROUP BY 或含 DISTINCT 的查询时卡住,状态长期停留在 Copying to tmp table 或直接报错:The table '#sql-xxxx' is full、Incorrect key file for table '/tmp/#sql_...',甚至触发内核级错误 OS error code 28: No space left on device。这不是 SQL 写得差,而是 MySQL 在 tmpdir 落盘临时排序文件时被磁盘写满硬拦截了。
快速确认 tmpdir 实际路径和空间瓶颈
别猜配置文件,直接查运行时值和系统挂载点:
- 进 MySQL 执行:
SELECT @@tmpdir;—— 注意返回值可能是/tmp、/var/tmp,也可能是空(表示用系统默认) - 在终端执行:
df -h $(mysql -Nse "SELECT @@tmpdir;")—— 直接看该路径所在分区剩余空间 - 若返回
tmpfs类型(如/tmp常是内存盘),重点看 Size 列:它通常只有几 GB,远小于物理磁盘,极易撑爆 - 顺手检查 inode:
df -i $(mysql -Nse "SELECT @@tmpdir;")—— 小临时文件极多时,可能空间剩得多但 inode 耗尽
不重启 MySQL 的临时救急方案(5.7.20+ / 8.0.12+)
生产环境不能停服?可用 SET GLOBAL 动态切换,但必须满足三个条件:
- 目标路径已存在,且 MySQL 进程用户(如
mysql或SYSTEM)有读写权限 - 该路径所在分区剩余空间 ≥ 当前最大表大小 × 1.2(留缓冲余量)
- 执行后立刻验证:
SELECT @@tmpdir;必须返回新路径,否则配置未生效
示例命令:SET GLOBAL tmpdir = '/data/mysql-tmp';
Windows phpEnv 环境下 tmpdir 权限与路径陷阱
phpEnv 封装的 MySQL 默认把 tmpdir 指向 C:/Windows/Temp 或 C:/phpEnv/tmp,这两处常因权限不足或路径含空格/中文导致静默失败:
- 路径必须用正斜杠:
tmpdir = D:/mysql_tmp(单反斜杠会被 MySQL 解析为转义) - 右键文件夹 →「属性」→「安全」→ 给
SYSTEM用户加「完全控制」权限(仅“修改”不够) - 改的是 MySQL 启动实际加载的配置文件(通常是
MySQL\my.ini,不是etc\my.ini) - 必须彻底杀掉所有
mysqld.exe进程(任务管理器里找),再重启服务,否则旧进程仍用老路径
真正麻烦的从来不是“怎么换路径”,而是换完后没人检查 tmp_table_size 和 max_heap_table_size 是否同步调大——这两个值太小,MySQL 会更频繁地把本可在内存做的排序强行落盘到新的 tmpdir,等于白换。











