leveldb支援資料的多個版本,可以擷取某個版本的快照,周遊或者查找這個版本中的key
class LEVELDB_EXPORT DB {
...
// Return a handle to the current DB state. Iterators created with
// this handle will all observe a stable snapshot of the current DB
// state. The caller must call ReleaseSnapshot(result) when the
// snapshot is no longer needed.
virtual const Snapshot* GetSnapshot() = 0;
// Release a previously acquired snapshot. The caller must not
// use "snapshot" after this call.
virtual void ReleaseSnapshot(const Snapshot* snapshot) = 0;
...
};
同時對某個key更新時,不會直接在原key上更新,而是送出一個版本号更大的record,原版本的key會一直保留,直到在compaction時,低版本的key被merge到高版本的key。
Version
Version儲存的是目前版本中的sstable和相關compaction資訊。通過引用計數管理生命周期,通過list方式組織。Version封裝了在compaction時對sstable的一系列操作。
class Version {
...
VersionSet* vset_; // VersionSet to which this Version belongs
Version* next_; // Next version in linked list
Version* prev_; // Previous version in linked list
int refs_; // Number of live refs to this version
// List of files per level
std::vector<FileMetaData*> files_[config::kNumLevels];
// Next file to compact based on seek stats.
FileMetaData* file_to_compact_;
int file_to_compact_level_;
// Level that should be compacted next and its compaction score.
// Score < 1 means compaction is not strictly needed. These fields
// are initialized by Finalize().
double compaction_score_;
int compaction_level_;
};
VersionEdit
每次compaction之後,會産生一個新的版本,新版本在sstable檔案組成上面和老版本上存在差異,這個差異通過VersionEdit表示,老版本通過應用VersionEdit之後,就可以得到新版本。
struct VersionEdit {
typedef std::set<std::pair<int, uint64_t>> DeletedFileSet;
// 比較器名稱
std::string comparator_;
// 日志編号,該日志之前的資料均可删除
uint64_t log_number_;
// 已經棄用
uint64_t prev_log_number_;
// 下一個檔案編号(ldb、idb、MAINFEST檔案共享一個序号空間)
uint64_t next_file_number_;
// 最後的seq_num
SequenceNumber last_sequence_;
//
bool has_comparator_;
bool has_log_number_;
bool has_prev_log_number_;
bool has_next_file_number_;
//
bool has_last_sequence_;
// 記錄每一層所對應需要壓縮的
std::vector<std::pair<int, InternalKey>> compact_pointers_;
// 相比上次version而言,本次需要删除的檔案有哪些
DeletedFileSet deleted_files_;
// 相比上次version而言,本次新增的檔案有哪些
std::vector<std::pair<int, FileMetaData>> new_files_;
};
VersionEdit中封裝了對上述幾個字段的序列化和反序列化。
Manifest
Manifest檔案可以看作是VersionEdit的日志,為了快速恢複需要将這些變更持久化到磁盤上。Manifest和WAL使用同樣的格式就VersionEdit,一個VersionEdit就是一條record。在DB重新開機時,通過解析目前Manifest檔案,就可以恢複到最新的版本。
VersionSet
通過VersionSet來管理多個Version,整個db隻有一個。

class VersionSet {
...
Env* const env_;
const std::string dbname_;
const Options* const options_;
TableCache* const table_cache_;
const InternalKeyComparator icmp_;
uint64_t next_file_number_;
uint64_t manifest_file_number_;
uint64_t last_sequence_;
uint64_t log_number_;
uint64_t prev_log_number_; // 0 or backing store for memtable being compacted
// Opened lazily
WritableFile* descriptor_file_;
log::Writer* descriptor_log_;
Version dummy_versions_; // Head of circular doubly-linked list of versions.
Version* current_; // == dummy_versions_.prev_
// Per-level key at which the next compaction at that level should start.
// Either an empty string, or a valid InternalKey.
std::string compact_pointer_[config::kNumLevels];
...
};