LevelDB组件-LOG
LevelDB组件-LOG
Write Ahead Log
LevelDB 写MemTable之前的操作。
格式

LevelDB 的 log 文件内容被组织成多个 32 KB
的定长块(block)。每个 block 由 1~N 个 record 组成(末尾可能会 padding)。
一个 record 由一个固定 7byte
的 header(checksum: uint32 + length: uint16 + type: uint8) 和实际数据(data: uint8[length])组成。
如果 block 的末尾不足 7 字节(小于 header 的大小),则全部填 0x00(padding),读取的时候会被忽略。
如果 block 的末尾刚好 7 字节,则填充一个 length 为 0 的 record。
将上层写入的数据称之为 user record
,以区分 block 中的 record
。由于 block 是定长的,而 user record 是变长的,一个 user record 有可能被截断成多个 record,保存到一段连续的 block 中。
因此,在 header 中有一个 type
字段用来表示 record 的类型:
enum RecordType {
// Zero is reserved for preallocated files
kZeroType = 0,
kFullType = 1, // 一个完整的 user record
// For fragments
kFirstType = 2, // user record 的第一个 record
kMiddleType = 3, // user record 中间的 record。如果写入的数据比较大,kMiddleType 的 record 可能有多个
kLastType = 4 // user record 的最后一个 record
};
示例
初始化整个 log 为空,假设有 3 条 user record:
A 大小为 1000 字节
B 大小为 97270 字节
C 大小为 8000 字节
32k = 32768 B
存储方式如图:

- A = 1000
- B_first = 32768-1000-7 = 31754
- B_mid = 32768-7 = 32761
- B_last = 97270-31754-32761 = 32755
- C = 8000
絮叨
分 block 的意义
如果不分block,每条record的长度不定,当某条record损坏,此时,我们无法找到下一条正常record从哪开始,相当于所有的record都被毁坏了。
如果划分block,即便每条record的长度不定,单block大小固定,如某条record损坏,此时,我们无法在当前block中找到下一条正常record从哪开始,但是可以找到下个block的位置,进而判断该block是否损坏,从而保证了不让所有的record都因一条record出现问题导致全部失效。