Tombstones — deletes that can come back
A delete is just a record that says 'absence' (a tombstone), and compaction may only drop it when no deeper level can possibly still hold the live record it is shadowing — get this wrong and the deleted key resurrects on the next read.
We've only put records in. Deletes are records too — and where they LIVE on the staircase, and how long, decides whether your delete actually sticks.
Scene 09
Tombstones — deletes that can come back
- Watch
- Try it
- Predict
- Capture
Six storyboard steps with the NAIVE rule (the last is the verdict). Watch the tombstone get dropped at step 3 and the older live record resurrect at step 5.
Highlighted lines are the ones running in the diagram right now.
def can_drop_tombstone(t, compaction_inputs, level):if level == BOTTOM_LEVEL: return True # nothing deeperfor deeper_level in levels_below(level):if deeper_level.has_overlapping(t.key):return False # older live may existreturn True# the WRONG rule (naive — used in scene's storyboard):def naive_can_drop(t, inputs):return not any(r.key == t.key for r in inputs)
# RocksDB DeleteRange — one record covers many keys:range_tombstone = (begin_key, end_key, seqno)# stored in a separate meta-block per SSTable# read path: check both per-key tombstones AND range tombstones# subject to the SAME retention rule across levels.# LevelDB has no DeleteRange; it must DELETE each key individually.
Where this sits in Build an LSM-tree storage engine (LevelDB / RocksDB style)
Scene 09 of 11, in the Sharp edges act — Tombstones, blocks, and the canvas.. Deletes are records. Drop a tombstone before all older live records are gone, and the deleted key resurrects. Same trap as Bitcask, restated for levels.
Up next. Reads, writes, deletes — all sorted out. But every read so far has touched a whole SSTable. Real systems read BLOCKS, cache them in RAM, and squeeze them with compression. That's the production reality.
All 11 scenes in Build an LSM-tree storage engine (LevelDB / RocksDB style) · Every curriculum