首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MVStore Online备份

MVStore Online备份
EN

Stack Overflow用户
提问于 2018-03-11 10:58:48
回答 1查看 146关注 0票数 1

MVStore文档中关于备份数据库的information有点模糊,而且我不熟悉所有的概念和术语,所以我想看看我提出的方法是否有意义。

我是一个Clojure程序员,所以请在这里原谅我的Java:

代码语言:javascript
复制
// db is an MVStore instance
FileStore fs = db.getFileStore();
FileOutputStream fos = java.io.FileOutputStream(pathToBackupFile);
FileChannel outChannel = fos.getChannel();
try {
  db.commit();
  db.setReuseSpace(false);
  ByteBuffer bb = fs.readFully(0, fs.size());
  outChannel.write(bb);
}
finally {
  outChannel.close();
  db.setReuseSpace(true);
}

下面是它在Clojure中的样子,以防我的Java不好:

代码语言:javascript
复制
(defn backup-db
  [db path-to-backup-file]
  (let [fs (.getFileStore db)
        backup-file (java.io.FileOutputStream. path-to-backup-file)
        out-channel (.getChannel backup-file)]
    (try
      (.commit db)
      (.setReuseSpace db false)
      (let [file-contents (.readFully fs 0 (.size fs))]
        (.write out-channel file-contents))
      (finally
        (.close out-channel)
        (.setReuseSpace db true)))))

我的方法似乎有效,但我想确保我没有遗漏任何东西,或者看看是否有更好的方法。谢谢!

另外,我之所以使用H2标签,是因为MVStore不存在,我也没有足够的名气来创建它。

EN

回答 1

Stack Overflow用户

发布于 2019-12-03 06:08:56

docs目前说:

可以随时备份持久化数据,甚至可以在写入操作期间进行备份(在线备份)。为此,首先需要禁用自动磁盘空间重用,以便始终将新数据附加到文件的末尾。然后,可以复制该文件。文件句柄可供应用程序使用。建议使用实用程序类FileChannelInputStream来执行此操作。

FileChannelInputStreamFileChannelOutputStream类将java.nio.FileChannel转换为标准的InputStream和OutputStream。BackupCommand.java中现有的H2代码展示了如何使用它们。我们可以使用Java9 input.transferTo(output);复制数据来对其进行改进:

代码语言:javascript
复制
    public void backup(MVStore s, File backupFile) throws Exception {
        try {
            s.commit();
            s.setReuseSpace(false);
            try(RandomAccessFile outFile = new java.io.RandomAccessFile(backupFile, "rw");
                FileChannelOutputStream output = new FileChannelOutputStream(outFile.getChannel(), false)){
                    try(FileChannelInputStream input = new FileChannelInputStream(s.getFileStore().getFile(), false)){
                        input.transferTo(output);
                    }
            }
        } finally {
            s.setReuseSpace(true);
        }
    }

请注意,当您创建FileChannelInputStream时,您必须传递false来告诉它在流关闭时不要关闭底层文件通道。如果您不这样做,它将关闭您的FileStore正在尝试使用的文件。该代码使用try-with-resource语法来确保正确关闭输出文件。

为了尝试这一点,我检查了mvstore代码,然后修改了TestMVStore,添加了一个类似于现有testSimple()代码的testBackup()方法:

代码语言:javascript
复制
    private void testBackup() throws Exception {
        // write some records like testSimple
        String fileName = getBaseDir() + "/" + getTestName();
        FileUtils.delete(fileName);
        MVStore s = openStore(fileName);
        MVMap<Integer, String> m = s.openMap("data");
        for (int i = 0; i < 3; i++) {
            m.put(i, "hello " + i);
        }

        // create a backup
        String fileNameBackup = getBaseDir() + "/" + getTestName() + ".backup";
        FileUtils.delete(fileNameBackup);
        backup(s, new File(fileNameBackup));

        // this throws if you accidentally close the input channel you get from the store
        s.close();

        // open the backup and verify
        s = openStore(fileNameBackup);
        m = s.openMap("data");

        for (int i = 0; i < 3; i++) {
            assertEquals("hello " + i, m.get(i));
        }
        s.close();
    }

在您的示例中,您正在读入一个必须放入内存的ByteBuffer。使用流transferTo方法使用当前(在Java11时)设置为8192字节的内部缓冲区。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49216195

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档