
春节假期结束,业务突然报异常,提示“磁盘空间不足,无法写入数据”,急急忙忙登服务器,敲下最常用的 df -lh 查看,结果傻眼了——磁盘使用率才50%,剩余空间足足有几十G!
明明有空间,却写不进去?难道是数据库出bug了?

其实不是数据库的问题,而是你忽略了Linux文件系统里一个关键知识点:inode,以及两个看似相似、实则完全不同的命令——df -lh 和df -i。
今天就用最接地气的实操,把这两个命令讲透,以后再遇到这种“空间有余、写入失败”的坑,1分钟就能定位解决,新手也能直接抄作业。
就像图中展示的这样,执行df -lh发现根目录使用率仅50%,剩余40G空间,但创建文件时却无情报错,此时就需要借助df -i命令排查根源。
一、 先搞懂:为什么空间够,却写不进去?
很多DBA及运维新手都有个误区:认为磁盘空间就是“存文件内容的地方”,只要剩余空间够,就能无限创建文件。其实不然。Linux文件系统在格式化时,会把磁盘分成两大部分,缺一不可:
简单类比:数据块是“仓库”,存的是实际货物;inode是“仓库台账”,记的是货物的位置、归属,每一个文件都必须占用一个inode。
而你的问题,就是“仓库还有空位,但台账已经记满了”——inode耗尽了,哪怕数据块还有剩余,也无法创建新文件(包括数据库的日志文件、临时文件)。

二、 df -lh 与 df -i 核心区别
这两个命令,前者管“仓库”,后者管“台账”,用法和作用完全不同,记准下面这张对比表,再也不会用混。
命令 | 核心作用 | 查看对象 | 关键指标 | 常见场景 |
|---|---|---|---|---|
df -lh | 查看磁盘空间使用情况 | 数据块block | 已用空间、剩余空间、使用率 | 判断磁盘是否真的“满了”,排查大文件占用 |
df -i | 查看inode使用情况 | 索引节点inode | 已用inode、剩余inode、使用率 | 空间充足但无法写入,排查inode耗尽问题 |
关键提醒:数据库运维中,这两个命令必须搭配使用!尤其是MySQL、PostgreSQL等数据库,会生成大量小日志文件(如binlog碎片、慢查询日志碎片),很容易耗尽inode,此时用df -lh完全查不出问题,只有df -i才能定位根源。
结合数据库运维场景,给大家一套完整的排查+解决流程,直接照做就行,不用瞎猜。
1. 用df -i 确认inode是否耗尽
登录数据库所在服务器,执行命令:
df -i执行后会显示所有挂载点的inode使用情况,重点看 IUse% 列(inode使用率):如果某一行的 IUse% 达到100%,说明这个挂载点的inode已经耗尽,就是它导致无法写入——这也是最常见的问题。
2. 定位耗尽inode的“罪魁祸首”
inode耗尽,99%的原因是:某个目录下存在大量小文件(比如数据库的binlog碎片、临时缓存文件、日志拆分后的小文件)。
执行下面的命令,快速定位哪个目录的小文件最多(以根目录为例,可替换为数据库安装目录,如 /data/mysql/mysql3306):
# 统计各目录下的文件数量,按从多到少排序(前10个)
find / -type f | awk -F '/' '{print $2}' | sort | uniq -c | sort -nr | head -10执行后,会显示文件数量最多的目录,比如看到 var 目录文件数量极高,再进一步排查 /data/mysql/mysql3306(数据库目录),大概率能找到大量的binlog小文件或慢查询日志碎片。
补充:如果想精准查找小于1M的小文件(最耗inode),可执行:
find /data/mysql/mysql3306 -type f -size -1M | wc -l3. 解决inode耗尽问题(分2种场景)
根据文件是否有用,分两种处理方式,核心是“删除无用小文件”或“增加inode数量”,优先选第一种(简单高效)。
场景1:无用小文件(如过期binlog、日志碎片)——直接删除

比如数据库的过期binlog文件,可通过以下命令安全删除(以MySQL为例):
# 1. 进入binlog目录(例如在/data/mysql/mysql3306/logs)
cd /data/mysql/mysql3306/logs
# 2. 删除3天前的所有binlog文件(根据实际情况调整天数)
find . -name "mysql-bin.*" -mtime +3 -delete
# 3. 重启MySQL(可选,确保日志生效)
systemctl restart mysqld删除后,再执行 df -i,就能看到inode使用率明显下降,此时就能正常写入数据了。
场景2:有用的小文件(如业务必需的小日志)——增加inode数量
如果小文件不能删除,就需要增加inode总数(注意:此操作需格式化磁盘,会清空数据,务必先备份!)。以ext4文件系统为例,执行以下命令(替换 /dev/sdX 为实际磁盘分区):
# 1. 备份该分区所有数据(关键!)
# 2. 卸载该分区
umount /dev/sdX
# 3. 格式化分区,指定inode数量(比如设置为100万)
mkfs.ext4 -N 1000000 /dev/sdX
# 4. 重新挂载分区
mount /dev/sdX /目标挂载点提示:XFS文件系统无法直接调整inode数量,需重新创建文件系统时指定inode密度。
4. 预防复发(数据库运维必做)
解决问题后,一定要做预防,避免下次再踩坑,尤其是数据库服务器,建议做好这2点:

四、 总结
很多运维新手栽在这个问题上,不是技术不够,而是忽略了“inode”这个细节。记住这两个命令的区别,下次再遇到类似问题,不用慌,1分钟就能定位解决。
如果觉得有用,转发给身边做运维、做数据库的同事,一起避坑~ 关注我,每天分享一个数据库实操干货,少走弯路!
关注微信公众号「数据库干货铺」,获取更多数据库运维干货。