1

我的目标是启用 MapDB 崩溃保护,如果发生崩溃,如何恢复数据。

我为 MapDB 启用了事务

DB db;
HTreeMap< String, String > mapDb;

db = DBMaker.fileDB( "walTest/file1.db" )
        .transactionEnable()
        .allocateStartSize( 64 *1024 *1024 )
        .allocateIncrement( 32 *1024 *1024 )
        .fileMmapEnable()
        .fileMmapEnableIfSupported()
        .fileMmapPreclearDisable()
        .cleanerHackEnable()
        .closeOnJvmShutdown()
        .make();

mapDb = db.hashMap( "Test" ) //$NON-NLS-1$
        .keySerializer( Serializer.STRING )
        .valueSerializer( Serializer.STRING )
        .createOrOpen();

for(int i=0; i<10000;i++)
{
    mapDb.put(""+i, "aaaaaaaaaaa bbbbbbbbbbbbbbbbbb cccccccccccccccccccc dddddddddddddddddd");
    if(i % 100 == 0) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    if(i == 5000)
    {
        db.commit();
    }
}

我看到它创建了 2 个文件,file1.db 和 file1.db.wal.0

现在,我重新启动服务器并使用以下代码读取 MapDB

System.out.println(mapDb.size());

输出为 5001 其他未提交的 5000 未恢复。

我在做 mapDb.size() 之前尝试使用 db.commit ,但它仍然没有帮助。

那么,wal 文件是如何防止服务器或 jvm 崩溃的呢?我们如何恢复wal文件?

4

1 回答 1

0

从最新版本(3.0.8)开始,我认为你不能。

查看源代码,它看起来有一些代码应该这样做,但它似乎是一个正在进行中的功能,它没有在内部使用,也没有外部方式来触发代码。

对于我发现的一些附加细节:使用.transactionEnable()MapDB 将触发 WAL 文件的创建,尽管它仅在应用程序运行时file1.db.wal.0使用它来允许。.rollback()在下一次启动时,即使 WAL 文件存在,它也会忽略内容,并立即开始写入文件,就好像它是新创建的并且是空的一样。

.transactionEnable()将 MapDB 的存储类设置为StoreWAL具有类变量wal,它是 的实例WriteAheadLog。WriteAheadLog 有一个子类WALReplay以及一个函数 open 和 replayWAL ,它们将 WALReplay 实例作为参数,但我不相信代码目前已准备好生产。

如果您真的想重播 WAL 文件,则可以通过以下方式实现:

  1. 使用反射从 db.getStore() 获取 wal 变量
  2. 创建 WALReplay 接口的实现
  3. 调用 replayWAL 或(最好)打开 wal 变量,传入 WALReplay 实现的实例。
于 2021-12-17T17:23:08.247 回答