Skip to main content

Module store

Module store 

Source
Expand description

MvStore — the in-memory version index sitting in front of the pager (Phase 11.3 skeleton).

Per docs/concurrent-writes-plan.md:

The MVCC store keeps an in-memory map keyed by RowID { table_id, row_key } whose value is a chain of RowVersion records. Each version carries begin/end timestamps and the row payload itself. Visibility for a reader transaction with begin-timestamp T is the textbook snapshot-isolation rule: pick the version whose begin <= T < end.

Phase 11.3 lands the standalone data structures + visibility logic so 11.4 can plug them into:

  • the executor’s read path when the connection is in MVCC journal mode (the super::JournalMode enum);
  • the commit path, which mirrors successful writes from the legacy Database::tables map into the MvStore at the assigned commit_ts and ends the previous latest version at the same timestamp.

Today nothing in the executor calls into this module. The PRAGMA journal_mode = mvcc switch parses but doesn’t change query behaviour. That’s intentional — committing to a half-wired read path before the write side exists would force 11.4’s commit-validation work into this PR. The two are coupled and ship together.

§Why one big mutex per chain rather than a per-row lock

v0 stores each row’s version chain inside an Arc<RwLock<Vec<RowVersion>>>. The outer map is a Mutex<HashMap<RowID, _>>. Two reasons not to over-engineer:

  1. The plan-doc explicitly calls this out:

    One chain per row, behind RwLock (or parking_lot::RwLock). The wait-free chain is a known follow-up; it’s not on the v0 critical path.

  2. The hot path is MvStore::read, which takes the outer lock to fetch the Arc<RwLock<…>>, drops it, then takes the chain’s RwLock in read mode for the visibility scan. The outer lock is held only long enough to clone an Arc.

When the commit path lands (11.4) and we observe contention, a sharded outer map (e.g. dashmap) becomes the obvious upgrade — same RowID → chain shape, just multiple shards. None of MvStore’s public surface assumes the inner storage shape, so the swap is local.

Structs§

MvStore
In-memory MVCC version index. Cheap to clone — the heavy state is behind Arcs.
RowID
Identifies a row across the MvStore. v0 keys by table name + rowid because the engine doesn’t yet have a stable numeric table_id (the schema catalog is keyed by name). When 11.5 lands a numeric table id (likely as part of the checkpoint integration so the index doesn’t carry a String per row), flip this to (u32, i64) — every consumer of RowID only uses it for hashing / equality, so the rename is local.
RowVersion
One link in a row’s version chain.

Enums§

MvStoreError
Errors returned by mutating MvStore operations. Read-side calls (read, visible_at) don’t error.
VersionPayload
What a RowVersion records. Present carries the row’s column values at the moment of commit; Tombstone records that the row was deleted at this version’s begin timestamp.

Type Aliases§

RowVersionChain
A row’s version chain. Newest version at the back — easy push_version semantics; reads scan from the back since that’s where most queries’ begin_ts lands.