1. 事件背景

在日常维护中,因发现 /var/lib/dnf 目录下 sqlite-wal 文件过大,为清理磁盘执行了删除操作。随后通过备份/系统手段恢复了数据。本文档记录了恢复后的数据压缩过程及长期维护建议。


2. 优化前后的详细数据对比 (ls -lh)

2.1 初始恢复状态 (18M)

此时数据库存在碎片,且包含运行时的临时映射文件(__db.*)。

[root@localhost ~]# ls -lh /var/lib/rpm/
total 18M
-rw-r--r--. 1 root root 2.2M  2月 13 16:33 Basenames
-rw-r--r--. 1 root root 8.0K  1月 29 16:32 Conflictname
-rw-r--r--. 1 root root 280K  2月 13 16:37 __db.001
-rw-r--r--. 1 root root  88K  2月 13 16:37 __db.002
-rw-r--r--. 1 root root 1.3M  2月 13 16:37 __db.003
-rw-r--r--. 1 root root 560K  2月 13 16:33 Dirnames
-rw-r--r--. 1 root root  13M  2月 13 16:33 Packages
...(其他小文件省略)...

[root@localhost ~]# du -s /var/lib/rpm/
17928    /var/lib/rpm/

2.2 重建优化后状态 (14M)

执行 rpm --rebuilddb 后,系统重新整理了 Berkeley DB 结构,删除了冗余碎片,并自动清理了 __db.* 文件。

[root@localhost ~]# rpm --rebuilddb
[root@localhost ~]# ls -lh /var/lib/rpm/
total 14M
-rw-r--r--. 1 root root 2.1M  2月 13 16:39 Basenames
-rw-r--r--. 1 root root 8.0K  2月 13 16:39 Conflictname
-rw-r--r--. 1 root root 484K  2月 13 16:39 Dirnames
-rw-r--r--. 1 root root  11M  2月 13 16:39 Packages
...(其他索引文件已同步重建)...

[root@localhost ~]# du -s /var/lib/rpm/
14096    /var/lib/rpm/

数据结论:通过重建索引,核心文件 Packages 从 13M 减小至 11M,目录总体积缩减了约 21.4%。


3. 核心原理解析

3.1 为什么会产生体积膨胀?

  1. BDB 碎片化:RPM 4.15 使用的 Berkeley DB 格式在频繁增删包后,文件内部会留下空洞。

  2. DNF WAL 机制:/var/lib/dnf/history.sqlite-wal 是 SQLite 的预写日志。在高并发写或事务未提交时,该文件会迅速增长(如你之前看到的 4.0M)。


4. 正确的“脱水”清理流程

若未来磁盘空间紧张,请按顺序执行以下操作,严禁使用 rm -rf 直接删除目录:

第一步:安全清理 DNF 缓存

# 清理下载的 rpm 包及旧的元数据
dnf clean all

第二步:压缩 RPM 数据库(针对 /var/lib/rpm)

# 重建索引并回收 BDB 碎片
rpm --rebuilddb

第三步:清理 DNF 历史记录(针对 /var/lib/dnf)

如果不依赖 dnf history 命令查看过去的操作记录,可执行:

# 停止 DNF 进程后删除
rm -f /var/lib/dnf/history.sqlite*

5. 预防性配置建议

为了防止数据库无限制增长,建议在 /etc/dnf/dnf.conf 中加入以下行:

[main]
# 限制事务历史记录保留条数(默认通常无限制或很大)
history_list_max=10

文档说明:本笔记适用于使用 RPM 4.15 (BDB 格式) 的系统(如 CentOS 8, RHEL 8 早期版本)。对于 RPM 4.16+ (SQLite 格式) 的系统,优化方式略有不同(主要使用 VACUUM)。