mysqldump 的临时文件默认存于 /tmp 或 sys_temp_dir 配置路径,受 --tmpdir 控制,需用 trap 结合 PID 唯一目录清理,避免误删;Docker/systemd 中需显式启用 shell 才能生效。

mysqldump 产生的临时文件藏在哪
MySQL 自身不生成备份临时文件,真正甩锅的是 mysqldump 进程——它在导出大表时可能用到磁盘临时空间,尤其是开启 --single-transaction 或遇到 BLOB 字段时,会把中间结果写进系统临时目录(/tmp 或 sys_temp_dir 配置路径),而不是数据库目录里。
常见错误现象:mysqldump 执行卡住、报 Got error 28 from storage engine(磁盘满)、或备份后发现 /tmp 下有大量 mysqlXXXXXX 开头的临时文件残留。
- 检查当前临时目录:运行
echo $TMPDIR,若为空则默认是/tmp - 确认 mysqldump 是否用了
--compress或管道压缩(如gzip),这类组合容易因子进程异常退出导致临时文件没清理 - 注意:这些文件属
mysqldump进程私有,不是 MySQL server 创建的,所以FLUSH LOGS或RESET MASTER完全无效
给 mysqldump 加清理钩子的实操方式
没有内置“备份完成回调”,得靠 shell 层兜底。核心思路是:用 trap 捕获进程退出信号,在退出前清理临时文件;同时避免误删其他进程的临时文件。
使用场景:定时备份脚本(crontab)、Docker 备份容器、CI/CD 中的数据库快照步骤。
- 只清理本进程创建的临时文件:用
$$获取当前 shell PID,生成带 PID 后缀的临时目录,例如/tmp/mysqldump_$$ - 必须用
trap 'rm -rf /tmp/mysqldump_$$' EXIT INT TERM,不能只写EXIT——否则 Ctrl+C 或 kill 会跳过清理 - 别直接
rm -rf /tmp/mysql*:可能误删其他正在运行的 mysqldump 实例的临时文件,甚至波及mysql.sock
简短示例:
#!/bin/bash TMP_DIR="/tmp/mysqldump_$$" mkdir -p "$TMP_DIR" trap 'rm -rf "$TMP_DIR"' EXIT INT TERM mysqldump --single-transaction --tmpdir="$TMP_DIR" mydb > backup.sql
tmpdir 参数对备份行为的实际影响
--tmpdir 不只是指定“放临时文件的地方”,它还会影响排序、JOIN、GROUP BY 等操作的磁盘缓冲位置。如果没显式传这个参数,mysqldump 会 fallback 到系统 tmpdir(通常是 /tmp),而该目录可能被 noexec 或 nodev 挂载,导致备份失败。
- 验证是否生效:在
mysqldump命令后加--verbose,看到类似Using temporary directory: /tmp/mysqldump_12345才算成功 - 权限问题:目标
--tmpdir目录必须对运行mysqldump的用户可读写,且不能是 root-only 目录(比如/root/tmp) - 性能提示:SSD 上的独立 tmpdir 比共用
/tmp更稳,尤其当备份并发高时,能减少 I/O 争抢
docker 或 systemd 环境下钩子失效的典型原因
在容器或服务管理器中跑备份脚本时,trap 很容易静默失效——因为主进程不是 shell,或者信号被截断了。
- Docker:如果用
docker run ... mysqldump直接执行命令,trap根本不会触发,因为没启动 shell 解释器;必须显式调用/bin/sh -c "..." - systemd:服务单元里
Type=oneshot默认不继承 shell 环境,trap无效;得加Shell=true或改用ExecStart=/bin/sh -c '...' - 最保险的做法:把清理逻辑写成独立脚本(如
cleanup_mysqldump_tmp.sh),在 crontab 或备份脚本末尾用find /tmp -name "mysqldump_*" -mmin +5 -delete定期扫尾(加-mmin +5防止删掉刚建的)
复杂点在于:临时文件生命周期和进程信号模型耦合太紧,一旦环境脱离交互式 shell,就得换思路——要么强化进程隔离(PID-based 目录),要么接受异步清理的延迟。


















