You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RocksDB WAL文件实际内容少但磁盘占用高的原因及优化方法

RocksDB WAL文件磁盘占用异常:原因分析与解决方案

问题现象

某RocksDB实例总磁盘占用约75M,其中WAL文件000006.log被du命令统计为占用71M,但ls -lh显示该文件实际仅40字节;手动复制该文件后,du显示新文件的磁盘占用降至4K。

一、异常原因

这是文件系统磁盘块未回收导致的,核心逻辑如下:

  • ls -lh显示的是文件的逻辑大小(即当前文件的有效数据长度),这里的40字节表示文件当前只有40字节的实际内容。
  • du统计的是文件实际占用的物理磁盘块数,显示71M说明该文件曾经被分配过71M的磁盘空间——可能是之前写入过大量数据,或者RocksDB预分配了空间,之后文件被截断到40字节,但文件系统没有立即释放多余的磁盘块。
  • 手动复制文件时,只会复制文件中实际有数据的部分,新文件仅占用对应大小的磁盘块(4K为文件系统默认块大小),原文件的闲置磁盘块需要等到文件被删除、覆盖写入,或文件系统执行空间回收后才会被释放。

二、降低WAL文件磁盘占用的方案

1. 调整RocksDB配置

  • 限制WAL总大小:设置Options.max_total_wal_size,当WAL文件总大小超过该阈值时,RocksDB会自动删除旧的WAL文件。
  • 控制单个WAL大小:通过Options.max_wal_size设置单个WAL文件的最大容量,避免单个文件过大。
  • 按需关闭WAL:如果业务可以容忍少量数据丢失(如测试环境),在WriteOptions中设置disableWAL = true,写入操作将不生成WAL文件。
  • 启用自动清理:确保Options.wal_dir配置正确,RocksDB会自动清理不再需要的归档WAL文件。

2. 手动回收磁盘空间

  • 对异常WAL文件执行备份-删除-还原操作:先复制文件到临时位置,删除原文件,再将备份文件复制回去,文件系统会自动回收闲置磁盘块。
  • 使用fallocate命令(支持XFS/EXT4等文件系统):执行fallocate -d 000006.log,直接释放文件中的空洞区域对应的磁盘块。

3. 确保RocksDB正常关闭

程序退出时必须调用db->Close()和delete db,让RocksDB完成WAL文件的清理、截断等收尾工作,避免异常关闭导致的磁盘空间残留。

4. 选择合适的文件系统

优先使用XFS、EXT4这类对文件空间回收效率更高的文件系统,减少磁盘块残留的概率。


相关命令输出

du -h * 输出

4.0K    000004.sst
71M     000006.log
4.0K    CURRENT
4.0K    IDENTITY
0       LOCK
128K    LOG
128K    LOG.old.1669987718576391
4.0M    MANIFEST-000005
8.0K    OPTIONS-000005
8.0K    OPTIONS-000008

ls -lh 输出

-rw-r--r--. 1 polaris polaris  966 Dec  2 18:58 000004.sst
-rw-r--r--. 1 polaris polaris   40 Dec  2 18:58 000006.log
-rw-r--r--. 1 polaris polaris   16 Dec  2 18:58 CURRENT
-rw-r--r--. 1 polaris polaris   37 Dec  2 18:57 IDENTITY
-rw-r--r--. 1 polaris polaris    0 Dec  2 18:57 LOCK
-rw-rw-r--. 1 polaris polaris  16K Dec  2 18:58 LOG
-rw-rw-r--. 1 polaris polaris  15K Dec  2 18:57 LOG.old.1669987718576391
-rw-r--r--. 1 polaris polaris  166 Dec  2 18:58 MANIFEST-000005
-rw-r--r--. 1 polaris polaris 4.5K Dec  2 18:57 OPTIONS-000005
-rw-r--r--. 1 polaris polaris 4.5K Dec  2 18:58 OPTIONS-000008

测试代码

#include <cassert>
#include <string>
#include <rocksdb/db.h>
#include <iostream>

using namespace std;
int main(int argc, char** argv) {
    rocksdb::DB* db;
    rocksdb::Options options;
    options.create_if_missing = true;
    rocksdb::Status status =
    rocksdb::DB::Open(options, "/dev/shm/testdb", &db);
    assert(status.ok());
    // Insert value
    status = db->Put(rocksdb::WriteOptions(), "Test key", "Test value");
    assert(status.ok());
    // Read back value
    std::string value;
    status = db->Get(rocksdb::ReadOptions(), "Test key", &value);
    std::cout << value << '\n';
    assert(status.ok());
    assert(!status.IsNotFound());
    // Read key which does not exist
    status = db->Get(rocksdb::ReadOptions(), "This key does not exist", &value);
    assert(status.IsNotFound());
}

内容的提问来源于stack exchange,提问作者Arindam Ghosh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 17:11:17