备份正在运行的rocksdb-instance

mid*_*dor 8 c++ rocksdb

我想以安全的方式将正在运行的rocksdb实例备份到同一磁盘上的某个位置,并且在备份期间不会中断处理。

我读过了:

我的问题是调用是否CreateNewBackupWithMetadata被标记为非线程安全来表示对此函数的两个并发调用将具有不安全的行为,或者表明对数据库的任何并发调用都将是不安全的。我已经检查了实现,它似乎正在创建一个检查点 - 第二篇文章声称该检查点用于 MyRocks 的在线备份 - 但我仍然不确定调用的哪一部分不是线程安全的。

我目前将此解释为,它是不安全的,因为CreateBackup...调用DisableFileDeletions和稍后EnableFileDeletions,当然,如果进行两个重叠的调用,可能会引起麻烦。由于 SST 文件是不可变的,我并不担心它们,但不确定通过插入修改 WAL 是否会损坏备份。我认为触发备份刷新应该可以防止这种情况,但我想确定一下。

任何指示或帮助表示赞赏。

mid*_*dor 8

我最终更深入地研究了实现方式,以下是我的发现:

回想一下,rocksdb 数据库由 Memtable、SST 和单个 WAL 组成,它可以保护 Memtable 中的数据免遭崩溃。

当您调用 时rocksdb::BackupEngine::CreateBackupWithMetadata,内部不会采取锁定,因此如果两个调用同时处于活动状态,则此调用可能会发生竞争。最值得注意的是,这个调用确实如此Disable/EnableFileDeletions,如果一个调用调用,而另一个调用仍然处于活动状态,那么另一个调用就会失败。

通过创建一个 ,在调用处于活动状态时,将文件从数据库复制到备份的过程不会被修改rocksdb::Checkpoint,如果flush_before_backup设置为 true,将首先刷新 Memtable,从而清除活动的 WAL。

在内部调用来CreateCustomCheckpoint调用. 获取全局数据库锁 ( ),可选择刷新 Memtable,并检索 SST 列表。如果在持有全局数据库锁时发生刷新,此时 WAL 必须为空,这意味着列表应始终包含代表从检查点开始的完整且一致的数据库状态的 SST 文件。由于 SST 是不可变的,并且备份调用关闭了通过压缩进行的文件删除,因此您应该始终获得完整的备份,而无需在数据库上保留写入。然而,这当然意味着当并发更新发生时,不可能确定备份中确切的最后写入/序列号 - 至少在创建备份后不检查备份是不可能的。DB::GetLiveFilesdb_filecheckpoint.ccGetLiveFiles_mutexGetLiveFiles

对于非刷新版本,可能存在 WAL 文件,这些文件是在与 不同的调用中检索的GetLiveFiles,中间没有锁,即这些文件不一定一致,但我没有进一步调查,因为非刷新情况是不适用于我的使用。