pub struct Snapshot {
pub version: u64,
pub in_progress: InProgressSet,
pub oldest_active: u64,
pub tx_id: u64,
pub locked_out: Option<(RelId, BTreeSet<usize>)>,
}Expand description
Per-statement / per-transaction snapshot.
Cheap to clone (Vec inside an InProgressSet is the only non-Copy field; bounded at active-tx count which is small).
Fields§
§version: u64The upper bound. A row whose xmin exceeds this is
in the snapshot’s future — invisible.
in_progress: InProgressSetIn-flight transactions at snapshot time.
oldest_active: u64Floor used by vacuum. Any row whose xmax < oldest_active
is dead to every live snapshot.
tx_id: u64The reading transaction’s OWN id. Used to implement “see
your own writes” — a row your transaction inserted is
visible to you even before commit. 0 for non-
transactional reads (autocommit SELECT).
locked_out: Option<(RelId, BTreeSet<usize>)>v7.39 (round 297, E3 Phase 1b) — rows a SKIP LOCKED pre-pass
found held by another transaction, as (relation, row indices).
It rides the SNAPSHOT because that is the only channel every row
source already threads. Adding the filter at individual scan
sites missed the real path three times running — index_access
alone performs the visibility test in ten places. A row that
someone else holds is, for this statement, exactly as
unavailable as a row the snapshot cannot see.
Implementations§
Source§impl Snapshot
impl Snapshot
Sourcepub const fn unbounded() -> Snapshot
pub const fn unbounded() -> Snapshot
A “see everything visible” snapshot — version at the current upper-bound u64, in-progress empty. Equivalent to the pre-v7.37.15 “Arc-snapshot reads the entire catalog” behaviour; useful for phase-A migration where the engine doesn’t yet track per-tx state.
Sourcepub fn new(
version: u64,
in_progress: InProgressSet,
oldest_active: u64,
tx_id: u64,
) -> Snapshot
pub fn new( version: u64, in_progress: InProgressSet, oldest_active: u64, tx_id: u64, ) -> Snapshot
Construct from explicit fields. The version cursor and in-progress set come from the engine’s per-process version counter at snapshot time; oldest_active is the MIN of every live snapshot’s version (vacuum reads it).
Sourcepub fn visible(&self, h: &RowHeader) -> bool
pub fn visible(&self, h: &RowHeader) -> bool
Should the row be visible to a reader holding this snapshot? The five-step rule mirrors PG’s HeapTupleSatisfiesMVCC.
- Self-write: if the row’s writer is THIS reader’s own tx, the row is visible (READ COMMITTED sees its own writes).
- xmin in the future: invisible.
- xmin still in-progress: invisible.
- Alive (xmax == ALIVE): visible.
- xmax in the future or in-progress: visible (the delete hasn’t committed yet from this reader’s point of view).
- xmax in the past + committed: invisible (deleted before this reader’s snapshot).
Sourcepub fn visible_with_status<O>(&self, h: &RowHeader, xact: &O) -> boolwhere
O: XactStatusOracle + ?Sized,
pub fn visible_with_status<O>(&self, h: &RowHeader, xact: &O) -> boolwhere
O: XactStatusOracle + ?Sized,
v7.37.15 (Phase C.2) — abort-aware visibility. Same as
Self::visible but consults a XactStatusOracle to
distinguish a committed version from an aborted one when
neither is in the snapshot’s in_progress set. Phase C.3’s
in-place write path needs this: a rolled-back or crash-orphaned
version leaves its xmin/xmax stamp physically present until
vacuum reclaims it, and the two-state Self::visible would
wrongly treat it as committed.
Two extra branches vs visible (marked NEW):
- xmin aborted → the insert never happened → invisible.
- xmax aborted → the delete never happened → still visible.
The frozen-and-alive fast path returns before any oracle call,
so steady-state scans over old data pay no oracle cost —
preserving the Phase B “≤5% overhead” result. Passing
AllCommitted makes this behave exactly like visible.