春节假期结束后的第一个工作日,我像往常一样检查数据库服务器状态时,突然发现MySQL服务虽然正常运行,但所有写入操作都报出"Disk full"错误。这让我瞬间警觉起来——毕竟磁盘空间不足是数据库运维中最危险的状况之一。
我立即执行了df -lh命令查看磁盘使用情况,结果却显示挂载点/var/lib/mysql所在分区仍有30%的剩余空间。这种矛盾现象让我意识到遇到了一个典型的"伪磁盘满"问题。作为DBA,这种情况需要立即处理,否则可能导致业务数据丢失。
注意:当MySQL报磁盘满错误但系统显示空间充足时,千万不要直接重启服务。这可能导致未完成的写入操作丢失,应先排查根本原因。
进一步执行df -i命令后,真相大白——该分区的inode使用率达到了100%。Linux系统中每个文件都需要占用一个inode,当inode耗尽时,即使实际磁盘空间充足,系统也无法创建新文件。这正是MySQL无法写入的根本原因。
bash复制# 查看inode使用情况的关键命令
df -i /var/lib/mysql
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda1 1.2M 1.2M 0 100% /var/lib/mysql
MySQL数据库运行时会产生多种类型的文件,每种都会消耗inode:
特别是当数据库中存在大量小表,或者频繁执行产生临时表的复杂查询时,inode消耗会急剧增加。我们的监控显示,春节期间批量数据处理任务创建了数十万个临时表文件。
面对inode耗尽的情况,我采取了以下应急措施:
bash复制# 安全删除MySQL临时文件
find /var/lib/mysql -name "#sql*" -exec rm -f {} \;
bash复制# 保留最近7天的binlog
PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);
sql复制-- 合并碎片化的小表
ALTER TABLE small_table1, small_table2
ENGINE=InnoDB ROW_FORMAT=COMPRESSED;
执行上述操作后,inode使用率从100%降至65%,MySQL写入功能立即恢复正常。通过以下命令确认:
bash复制# 检查当前inode使用率
watch -n 1 'df -i /var/lib/mysql'
# 验证MySQL写入能力
mysql -e "CREATE TEMPORARY TABLE test.tmp_test (id INT); DROP TABLE test.tmp_test;"
原系统配置存在明显缺陷:
/var/lib/mysql所在分区inode总数仅1.2M个对于MySQL数据库服务器,建议采用以下配置:
bash复制# 创建XFS文件系统(inode动态分配)
mkfs.xfs -f -i size=512 -n size=8192 /dev/sdb1
bash复制# /etc/fstab 配置示例
/dev/sdb1 /mysql_data xfs noatime,nodiratime,logbsize=256k,logbufs=8 0 0
ini复制[mysqld]
# 减少临时文件产生
tmp_table_size = 64M
max_heap_table_size = 64M
# 控制binlog数量
expire_logs_days = 7
binlog_format = ROW
建立完善的监控体系,重点关注:
示例Prometheus监控规则:
yaml复制- alert: HighInodeUsage
expr: 100 * (node_filesystem_files_free{device="/dev/sdb1"} / node_filesystem_files{device="/dev/sdb1"}) < 20
for: 10m
labels:
severity: critical
annotations:
summary: "Inode usage high on {{ $labels.mountpoint }}"
设置定期维护任务:
bash复制#!/bin/bash
# 每周清理旧临时文件
find /var/lib/mysql -name "#sql*" -mtime +1 -delete
# 每月优化碎片化表
mysql -e "SELECT CONCAT('OPTIMIZE TABLE ', table_schema, '.', table_name, ';')
FROM information_schema.TABLES
WHERE DATA_FREE/power(1024,3) > 1 INTO OUTFILE '/tmp/optimize_tables.sql'"
mysql < /tmp/optimize_tables.sql
在实际处理过程中,我总结了以下关键经验:
不要依赖单一指标:
df -h和df -idf -i纳入Zabbix/Prometheus基础监控临时文件处理技巧:
/tmp或/var/tmptmpdir参数指定专用临时目录文件系统选型建议:
表设计最佳实践:
这次故障让我深刻认识到,数据库运维不能只看表面指标。一个成熟的DBA应该建立立体化的监控体系,同时理解存储系统的底层原理。特别是在节后业务高峰期,更要提前检查系统资源余量,防患于未然。