key_skipped_count 是 rocksdb 里面的 key 的概念
而 total_keys / process_keys 是我们的 mvcc key 的概念
两者虽然都叫 “key”,但实际上是不同的东西
rockdb 提供的是 key-value 的 api
tidb 会用这套 kv 的 api 实现 mvcc 的 api
mvcc 的 key 是这样的,比如说一开始,写入一条 a = 3 的记录
那么 mvcc 层的 api 对外展示是 a => 3
而 mvcc 层的内部实现是 a_v0 => 3
从 rocksdb 层提供的 api 观察是 a_v0 => 3
而 rocksdb 层内部实现,a_v0[0] => 3
之后修改这条记录, 变成 a = 4
那么 mvcc 层的 api 对外展示是 a => 4
而 mvcc 层的内部实现是
a_v0 => 3
a_v1 => 4
到 rocksdb 层也是这样,因为 mvcc 是用 rocksdb 提供的 api 来实现的
a_v0 => 3
a_v1 => 4
接下来,我们删除 a
那么 mvcc 层的 api 对外展示是 a => 3
而 mvcc 层的内部实现是
a_v0 => 3
a_v1 => 4
a_v2 => tombstone
删除都不是真的删除,而是标记为 tombstome
我们 mvcc 层的 GC 是做什么呢?是清理掉 mvcc 遗留的历史版本数据,比如这里,做完 GC 之后会变成:
a_v2 => tombstone
这两条 key 去哪里了呢? 这两条 key 被我们调用 rocksdb 的 api,delete 掉了
a_v0 => 3
a_v1 => 4
关键点来了!rocksdb 的删除,它也不是真正的删除,在它内部其实也是标记删除,直到 compaction 之后才真正意义上删除。所以这两个 key 即使在 mvcc 层做过 GC 了,也还在 rocksdb internal 的 tombstone,影响 key_skipped_count … 直到在 rocksdb 那层也做过 compaction