Replace ingest-table whole-table clear with incremental per-page drain

XMLWordPrintableJSON

    • Type: Improvement
    • Resolution: Unresolved
    • Priority: Major - P3
    • None
    • Affects Version/s: None
    • Component/s: Reconciliation
    • None
    • Storage Engines - Transactions
    • 227.735
    • SE Transactions - 2026-08-14
    • 8

      Context

      WT-17989 identified that step-up currently drains an ingest table and then clears it with a whole-table non-transactional truncate. The clear walks every ingest key while holding one read snapshot. For a large ingest table under cache pressure, the scan can pin the global oldest transaction ID long enough to prevent update reclamation, leave eviction stuck, and receive WT_ROLLBACK with WT_OLDEST_FOR_EVICTION.

      WT-17989 uses a temporary standalone mitigation that sets WT_SESSION_IGNORE_CACHE_SIZE during the final clear. This ticket tracks the long-term design that removes the long-lived snapshot and releases completed ingest pages incrementally.

      Goal

      Replace the drain-then-whole-table-clear workflow with a single incremental row-store drain that completes one key and one source leaf at a time. The drain must release its read snapshot after each key and hand a completed non-root ingest leaf to eviction as soon as the walk crosses its boundary.

      Proposed MVP

      • Scope the first implementation to BTREE_ROW.
      • Preserve the existing fail-fast behavior. Do not add drain retry, resume, or a persistent recovery frontier.
      • Snapshot the truncate list into worker-owned entries sorted by timestamp and transaction ID before workers start. Keep per-drain frontier state separate from the shared truncate-list objects.
      • Walk the ingest tree once in key order.
      • For each ingest key:
        • Replay stable-only portions of covering truncate ranges in timestamp order, partitioning each closed truncate range around visited ingest keys.
        • Read and merge the stable key's version chain with ingest versions and covering truncate tombstones, preserving the existing total version order and prepared-update behavior.
        • Finish all stable-side work, reset borrowed cursor state, localize values, and explicitly release the read snapshot. Verify the drain does not carry one pinned_id across keys.
        • Apply the globally visible non-transactional tombstone to the ingest source key.
        • Advance truncate frontier state only after the stable chain and source tombstone both complete. Pre-grow any required key buffers so no fallible allocation occurs after source deletion.
      • Hold an extra hazard on the current non-root ingest leaf. When the walk crosses a leaf boundary, reset the completed leaf's prune gate, mark it EVICT_SOON, consume the drain hazard in a direct no-split eviction attempt, and accept EBUSY while preserving sticky eviction intent.
      • At normal EOF, finish the final leaf, replay only remaining truncate-range remainders, release the EOF snapshot, and clear the shared truncate list after the whole work item succeeds.
      • Remove the trailing whole-table ingest clear and diagnostic empty-table scan from the successful drain path.

      Correctness invariants

      • Stable-side work for a key completes before the irreversible ingest source tombstone.
      • A truncate's frontier names only the last ingest key whose stable chain and source tombstone both completed.
      • Visited ingest keys are handled exactly once by inline version merging; stable-only keys are handled exactly once by restricted truncate replay.
      • Snapshot release occurs only after all cursors have released borrowed values.
      • A completed leaf is never accessed after its drain hazard is transferred to eviction.
      • Errors retain the current connection-fatal semantics; recovery starts from the existing durable checkpoint boundary rather than resuming a partial drain.

      Definition of done

      • The original pinned WT-17989 format reproduction passes without WT_SESSION_IGNORE_CACHE_SIZE and without WT_ROLLBACK retry.
      • Deterministic tests verify per-key snapshot release and that global oldest can advance between consecutive drained keys.
      • Multi-leaf tests verify completed pages are evicted or left marked EVICT_SOON before later leaves finish, including other-hazard and competing-eviction EBUSY cases.
      • Tests cover stable/ingest version ordering, prepared updates, empty logical streams, overlapping truncates, inclusive range endpoints, and stable-only truncate gaps.
      • Tests verify EOF cleanup, real-error ownership transfer, no trailing source scan, and no page split during direct eviction.
      • Cache-residency measurements demonstrate that completed leaves are released incrementally rather than retained until whole-table completion.
      • Relevant Python/csuite coverage and x86/arm64 disaggregated format stress variants pass.

            Assignee:
            Shoufu Du
            Reporter:
            Shoufu Du
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: