必须通过修改my.cnf或my.ini的[mysqld]段设置tmpdir路径,确保目录存在、属主为mysql(Linux)或SYSTEM(Windows)、权限正确,重启MySQL服务后执行SELECT @@tmpdir验证生效,动态修改SET GLOBAL tmpdir无效。

确认 MySQL 实际使用的 tmpdir 路径
MySQL 启动后不一定用系统默认的 /tmp 或 C:\Windows\Temp,它优先读取配置文件中的 tmpdir 值。如果没配,才 fallback 到编译时指定的路径(Linux 常为 /tmp,Windows 常为 C:\Windows\Temp)。
查当前生效值:SELECT @@tmpdir;
若返回空或 /tmp,但你实际想换路径,就得手动配——别依赖“默认可用”。
检查并修复 tmpdir 目录的属主与权限
MySQL 进程以 mysql 用户(Linux/macOS)或 SYSTEM/自定义服务账户(Windows)运行,不是 root 或当前登录用户。
常见错误现象:Can't create/write to file '#sql_5c0_0.MYD' 出现在 /tmp 下,但 ls -ld /tmp 显示权限是 drwxr-xr-x(即其他用户无写权)
正确做法:
- Linux/macOS:确保目录存在、属主为
mysql、权限为755或750(不推荐777)sudo mkdir -p /var/tmp/mysqlsudo chown mysql:mysql /var/tmp/mysqlsudo chmod 750 /var/tmp/mysql - Windows:右键目标目录 → “属性” → “安全” → 编辑 → 添加
SYSTEM或 MySQL 服务账户 → 勾选“修改”“写入” - 若用 NFS 或挂载盘,确认支持
flock(),否则临时表操作会静默失败
绕过杀软/SELinux 对 tmpdir 的拦截
即使权限全对,McAfee、Windows Defender 或 SELinux 也可能在 open() 阶段直接拒绝写入,错误日志里往往只报 Errcode: 13 - Permission denied,没提策略名。
快速验证方法:
- Linux(SELinux):
ausearch -m avc -ts recent | grep mysqld,若有输出,说明被拦;临时放行:sudo setenforce 0(仅测试) - Windows(McAfee):进 VirusScan → “按访问扫描” → “排除项” → 添加你的
tmpdir路径,勾选“读取时”和“写入时” - 不要长期禁用防护机制,而是用
audit2allow(SELinux)或 McAfee 策略编辑器生成精准规则
tmpdir 配置必须重启生效且不能动态修改
SET GLOBAL tmpdir = '/new/path' 是非法操作,MySQL 会报错 Variable 'tmpdir' is a read only variable。
必须改配置文件:
- Linux:在
/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf的[mysqld]段加:tmpdir = /var/tmp/mysql - Windows:在
my.ini的[mysqld]段加:tmpdir="D:/mysql/temp"(路径含空格必须加双引号) - 改完务必重启服务:
sudo systemctl restart mysqld(Linux)或net stop mysql && net start mysql(Windows) - 重启后立刻执行
SELECT @@tmpdir;确认值已更新,再跑一次触发临时表的查询(如SELECT * FROM t1 ORDER BY col LIMIT 1000000)验证是否真生效
真正容易被忽略的是:MySQL 在启动阶段就会尝试往 tmpdir 写一个测试文件(如 is_writable),这个动作发生在任何 SQL 执行之前。所以哪怕你只是改了配置、没重启,或者重启后没检查 @@tmpdir 是否生效,后续所有依赖临时文件的操作(排序、分组、导出、ALTER TABLE)都可能突然失败,且错误信息里不会提示“tmpdir 不对”,只甩一句 Can't create/write to file。











