-
Type:
Task
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: Schema Management
-
None
-
Storage Engines - Foundations
-
298.568
-
None
-
None
Problem
In disaggregated storage there are two intended usage models:
- Epoch world: the stable schema epoch is set first, then tables are created. A table created while the epoch is set is flagged WT_BTREE_AWAITS_PUBLISH, held in memory, and only written to a checkpoint once it has been published. This is the publish protocol.
- No-epoch world (legacy, e.g. test/format): tables are created with no stable epoch ever set. They are never flagged and are written like ordinary local tables.
The world is decided at table-create time by whether the stable epoch is set. The gap: nothing stops a caller from mixing the two. If a table is created before the stable epoch is set (no-epoch world) and the caller then tries to publish it, the publish silently proceeds even though the table never went through the publish protocol and was never held for publication. The ordering mistake – intending epoch world but creating before setting the epoch – is invisible.
Chosen solution
WT_SESSION::publish panics when the stable disaggregated schema epoch is not set. Publishing is only meaningful in epoch world, so a publish with no epoch set is an unrecoverable protocol violation rather than a recoverable bad argument. This is config-free and adds no new persistent state: the existing has_stable_disaggregated_schema_epoch latch (monotonic, never returns to NONE, restored on restart from the persisted checkpoint epoch) already records that epoch world was entered. The existing create-time gate is unchanged.
Alternatives considered
- A. Explicit connection-mode config (e.g. disaggregated=(schema_epochs=true)): declare the world at connection open and gate create/publish/checkpoint on it. Most explicit and restart-safe, but a config becomes public API that is very hard to remove later, and we expect this distinction to be temporary. Rejected.
- B. First-operation latch: a tri-state world (UNKNOWN / EPOCH / NO_EPOCH) latched by whichever happens first – the first set_stable_epoch (EPOCH) or the first table create (NO_EPOCH), enforced at whichever comes second. Config-free and catches the mistake before any data is written, but adds new connection state and mixing rules. Kept in reserve if enforcing at publish proves too late or too coarse.
- C. EINVAL at publish: same check but returning EINVAL instead of panicking. Rejected in favour of a panic because creating before the epoch is a protocol violation that should not be silently recoverable.
- D. Enforce/detect at checkpoint: at checkpoint, panic if a disaggregated table not awaiting publish holds data at or below the checkpoint (created pre-epoch). Catches the concrete harm regardless of ordering, but later than publish. Kept in reserve.
Risk
Any caller (including mongod) that publishes before setting a stable epoch will now panic, which is connection-fatal. This must be confirmed against the server's startup ordering; if a caller legitimately bootstraps by publishing first, switch to alternative B.
- is related to
-
WT-18099 (Leader) create/drop/create above stable schema epoch survives database recovery
-
- Closed
-
-
WT-18112 Fix step-up losing follower-published table when no prior follower checkpoint
-
- Closed
-
- related to
-
WT-18196 schema_disagg_abort panics on first publish because the stress test never sets the stable disaggregated schema epoch
-
- Closed
-