前文回顧
內(nèi)容上,Manifest 文件保存了整個 LevelDB 實例的元數(shù)據(jù),比如:每一層有哪些 SSTable。
格式上,Manifest 文件其實就是一個 log 文件,一個 log record 就是一個 VersionEdit。
VersionEdit
LevelDB 用 VersionEdit 來表示一次元數(shù)據(jù)的變更。Manifest 文件保存 VersionEdit 序列化后的數(shù)據(jù)。LevelDB 的元數(shù)據(jù)變更包括:
std::string comparator_;
uint64_t log_number_;
uint64_t prev_log_number_;
uint64_t next_file_number_;
SequenceNumber last_sequence_;
std::vector<std::pair<int, InternalKey> > compact_pointers_;
DeletedFileSet deleted_files_;
std::vector<std::pair<int, FileMetaData> > new_files_;
- comparator_:比較器的名稱,這個在創(chuàng)建 LevelDB 的時候就確定了,以后都不能修改。
- log_number_:最小的有效 log number。小于 log_numbers_ 的 log 文件都可以刪除。
prev_log_number_:已經(jīng)廢棄,代碼保留是為了兼容舊版本的 LevelDB。- next_file_number_:下一個文件的編號 。
- last_sequence_:SSTable 中的最大的 sequence number。
- compact_pointers_:記錄每一層要進行下一次 compaction 的起始 key。
- deleted_files_:可以刪除的 SSTable(level-no -> file-no)。
- new_files_:新增的 SSTable。
VersionEdit 通過成員函數(shù) EncodeTo 和 DecodeFrom 進行序列化和反序列化。一個全部字段都填上的 VersionEdit 序列化后的內(nèi)容格式如下(注意,并不是每個 VersionEdit 都會由下面所有字段的內(nèi)容,一般只有一部分):
kComparator comparator_
kLogNumber log_number_
kPrevLogNumber prev_log_number_
kNextFileNumber next_file_number_
kLastSequence last_sequence_
kCompactPointer level internal_key kCompactPointer level internal_key ...
kDeletedFile level fileno kDeletedFile level fileno ...
kNewFile level fileno file-size smallest largest kNewFile level fileno file-size smallest largest ...
Version

Version 是 VersionEdit 進行 apply 之后得到的數(shù)據(jù)庫狀態(tài)——當前版本包含哪些 SSTable,并通過引用計數(shù)保證多線程并發(fā)訪問的安全性。讀操作要讀取 SSTable 之前需要調(diào)用 Version::Ref 增加引用計數(shù),不使用時需要調(diào)用 Version::UnRef 減少引用計數(shù)。
VersionSet
VersionSet 是一個 Version 的集合。
隨著數(shù)據(jù)庫狀態(tài)的變化,LevelDB 內(nèi)部會不停地生成 VersionEdit——進而產(chǎn)生新的 Version。此時,舊的 Version 可能還在被正在執(zhí)行的請求使用。所以,同一時刻可能存在多個 Version。
VersionSet 用一個鏈表將這些 Version 維護起來,每生成一個 Version 就往這個鏈表尾部插入一個節(jié)點(AppendVersion)。
更多的細節(jié)會留在讀操作與 Compaction 的時候介紹。