排查 df -h 与 du -h 磁盘空间显示不一致的问题
背景
- Linux 服务器,LVM 卷
/dev/mapper/rsdata-dmdata挂载在/rscloud/dmdata - 已用
rm -f删除 100G+ 达梦数据库审计文件 df -h仍显示 100%(186G used / 196G total)du -h仅显示约 37G
根因分析
核心原因:进程持有已删除文件的文件句柄(File Descriptor)。
在 Linux 中:
rm -f仅删除**目录项(directory entry)**,即文件名与 inode 的映射关系- 如果有进程已经打开了该文件(open()),则该文件的 inode 及数据块仍被引用
- 磁盘空间只有在所有持有该文件句柄的进程都 close() 后才会真正释放
df统计的是文件系统层面的已分配块(allocated blocks),包括被删除但仍有进程引用的文件du统计的是通过目录树可遍历到的文件,看不到已删除但仍被引用的文件
所以:df ≈ du + 已删除但进程仍在引用的文件大小。
排查步骤
Step 1:确认是否存在被进程持有的已删除文件
# 查看 /rscloud/dmdata 下所有被进程打开但已删除的文件
lsof +L1 /rscloud/dmdata或者:
# 更通用的方式
lsof -nP | grep '(deleted)' | grep '/rscloud/dmdata'Step 2:若 lsof 不可用,检查 /proc 文件系统
# 查看所有进程的 fd 信息
find /proc/*/fd -type l -lname '*/rscloud/dmdata/* (deleted)' 2>/dev/null或更精确地:
ls -la /proc/*/fd/ 2>/dev/null | grep '/rscloud/dmdata.*(deleted)'Step 3:确认是哪个进程占用了句柄
在 Step 1/2 的输出中,会看到类似:
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
dmserver 12345 dmdba 11w REG dm-0 100G 654321 /rscloud/dmdata/data/... (deleted)
重点关注:
- PID:进程 ID
- COMMAND:进程名称
- FD:文件描述符(w 表示写模式打开)
Step 4:释放磁盘空间
有两种方式:
方式一:重启持有文件的进程(推荐)
# 如果确认是达梦数据库进程
systemctl restart DmService # 或对应的达梦服务名或者手动 kill(谨慎使用):
# 先确认 PID,然后向进程发送信号
kill -HUP <PID> # 优先尝试 SIGHUP,部分进程会重新加载而不退出
# 或
kill <PID> # 正常终止进程方式二:清空文件而非删除(恢复后生产环境建议)
如果未来仍有类似问题,正确的做法是清空审计文件而非删除:
# 清空文件内容而非删除文件
: > /path/to/audit_file.log
# 或
cat /dev/null > /path/to/audit_file.log
# 或
truncate -s 0 /path/to/audit_file.log这样文件 inode 不变,进程句柄不受影响,空间立即释放。
Step 5:验证空间是否释放
df -h /rscloud/dmdata达梦数据库审计文件管理建议(预防措施)
- 开启审计文件自动清理:配置达梦数据库的定期清理策略
- 设置审计文件大小限制:避免单个审计文件无限增长
- 使用 truncate 方式清理:避免
rm -f后句柄残留 - 监控磁盘使用率:设置告警阈值(如 80%),及早发现
参考资料
lsof:List Open Files,查看进程打开的文件列表/proc/*/fd/:每个进程的文件描述符目录- Linux 文件删除原理:
rm删除目录项 → 文件引用计数归零 → 空间真正释放