Multi-process WAL: PrepareTransactionAsync and the direct commit paths bypass the commit and cross-process writer locks
Maintainers usually reply within 2 days
Nobody has claimed this yet.
- #246 by @CaffeinatedCoder — closed without merging
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 35/100
Research direction
Start with StorageEngine.PrepareTransactionAsync, CommitTransactionAsync(ulong), and MarkTransactionCommittedAsync(ulong), then compare their WAL append sequence with ProcessBatchAsync and the shared-WAL catch-up changes from #169. Trace how checkpoint truncation handles prepared transactions and how multi-process appends publish WAL offsets and the SHM page index. Done means prepared records survive until commit or abort, and direct commit records are safely appended and visible across processes, or these paths are rejected in multi-process mode.
Written by the indexing model from the issue text.
Description
Found during the review of #169.
StorageEngine.PrepareTransactionAsync (both overloads) writes Begin and Write records to the WAL without holding _commitLock or, in multi-process mode, the SHM writer lock. A checkpoint's WAL truncation (TryTruncateWalAsync) only excludes writers that hold _commitLock, so it can run between a prepare and the matching commit and drop the prepared transaction's records.
The in-library flow (Transaction.PrepareAsync then CommitAsync) rewrites all pages through group commit, so the commit itself survives today. But the prepared records are not durable the way a 2PC prepare should be, and after such a truncation recovery can't see a prepared-but-uncommitted transaction. Prepare records can also interleave with a group-commit batch in the WAL stream, because only the per-record WAL lock serialises them.
Related: the public direct commit paths CommitTransactionAsync(ulong) and MarkTransactionCommittedAsync(ulong) take _commitLock, but in multi-process mode they do not:
- take the SHM writer lock;
- catch up with the shared WAL and move to its end before appending, as group commit does since #169;
- publish the new WAL end offset or the SHM page index, or advance
_lastKnownWalEndOffset.
So their records can overwrite another process's records or stay invisible to other processes, and another process's truncation can discard them. Nothing in the library calls them, but they are public.
Possible fix: route prepare and the direct commit paths through the same locked append sequence as ProcessBatchAsync (_commitLock, SHM writer lock, TryCatchUpWithSharedWal, SeekToEnd, append, publish), and keep a prepared transaction's records from being truncated until it commits or aborts. Alternatively, reject these paths when AllowMultiProcessAccess is set.
- Dominant language
- C#
- Stars
- 66
- Forks
- 6
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 58
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from EntglDb/BLite
-
GdprMode.Strict warns that deleted documents are not zeroed, but every delete zero-fills themPossibly taken @CaffeinatedCoder claimed this 3 days ago. Openbug gdpr package/core severity/low
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
EntglDb/BLite#299 · 1 comment ·
Maintainers usually reply within 2 days
-
bug package/core severity/medium triage
Difficulty 4/5 3-5 days Newbie friendliness 54/100
Maintainers usually reply within 2 days
-
bug package/core severity/medium
Difficulty 4/5 3-5 days Newbie friendliness 48/100
EntglDb/BLite#322 · 1 comment ·
Maintainers usually reply within 2 days
-
enhancement package/core
Difficulty 4/5 3-5 days Newbie friendliness 48/100
EntglDb/BLite#320 · 1 comment ·
Maintainers usually reply within 2 days
-
BLiteSession.Rollback() does not await the rollback: it returns while the transaction is still active, and failures go unobservedPossibly taken @CaffeinatedCoder claimed this 3 days ago. Openbug package/core severity/medium
Difficulty 3/5 1-2 days Newbie friendliness 78/100
EntglDb/BLite#307 · 1 comment ·
Maintainers usually reply within 2 days
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
bug priority: P2
Difficulty 1/5 Under an hour Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
IridiumIO/CompactGUI#699 ·
Maintainers usually reply within 3 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
Maintainers usually reply within 1 day
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day