Skip to content

Data loss in multi-process mode: pages replayed before another process truncated the WAL are written back over newer data #197

Closed

Description

@CaffeinatedCoder

Data loss. Found by @mrdevrobot while reviewing #169. The defect is on main too; the code references below are to the #169 branch (b721fee).

In multi-process mode, the pages an engine replayed from the shared WAL into its _walIndex stay there after another process checkpoints and truncates the WAL. The next checkpoint in this engine then writes those stale images over newer data on disk.

Sequence

  1. A commits page P = 0x11.
  2. B begins a transaction and replays the record, so B's _walIndex now holds P = 0x11.
  3. A commits P = 0x22, checkpoints (P = 0x22 on disk) and truncates the WAL.
  4. B begins again. It sees shmEnd < lastKnown and resets its bookmark, but keeps the stale P = 0x11 entry in _walIndex.
  5. B checkpoints and writes P = 0x11 over 0x22 on disk.

A freshly opened engine now reads 0x11: A's committed write is lost.

Where

StorageEngine.TryCatchUpWithSharedWal (StorageEngine.Transactions.cs ~L76-80) detects the truncation (shmEnd < lastKnown) but only resets the bookmark.

Possible fix

When the truncation is detected, drop the entries replayed from other processes, which are not this engine's own pending commits. Better still, keep a WAL generation counter in the SHM that every truncation increments. An engine that sees a new generation discards everything it replayed and starts over from offset 0. The same counter would also close the window described in #199.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    • Status
      Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions