Remove global MongoDB storage replication lock - #796
Open
rkistner wants to merge 12 commits into
Open
Conversation
rkistner
added this pull request to stack #794
September 10, 2026 15:34
🦋 Changeset detectedLatest commit: 5b50b8a The changes in this PR will be included in the next version bump. This PR includes changesets to release 12 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
rkistner
force-pushed
the
preallocate-opid
branch
from
September 10, 2026 16:30
0c9334d to
83d00af
Compare
rkistner
force-pushed
the
preallocate-opid
branch
from
September 10, 2026 17:39
83d00af to
cadddc1
Compare
rkistner
marked this pull request as ready for review
September 11, 2026 08:39
This comment was marked as resolved.
This comment was marked as resolved.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Currently, only one replication stream at a time can flush changes. This is due to:
These can become a bottleneck if there is high replication throughput while also doing initial replication. And we don't need that: We don't need absolute ordering of operations between replication streams.
This changes the implementation to pre-allocate large ranges of op_ids, separate from the flush transaction, to allow concurrent flushes.
This affects all MongoDB storage versions.
This does not affect concurrency within a replication stream.
This does not change the storage format, although it does tweak how it is used. It remains compatible with older service versions on the same storage version.
Latency within a stream can be slightly improved by this PR: For a small commit, storage round-trips on MongoDB 8, storage v4, can be reduced from 12 to 9 in some cases. Most of this gain is from combining flush and checkpoint commit into one transaction. Bulk replication throughput (initial replication or replication catch-up) is not affected by this.
Pre-allocated ranges
A replication job now pre-allocates ranges of 64K op_ids at a time. When it hits a 16K low-water mark, it requests another range. If a single batch manages to exhausts the available ids before the low-water mark logic can kick in, it fails the transaction, requests another range, then retries. That case should be rare.
A single range is used across multiple batches in a replication job, until the range is exhausted or the job is stopped. It does not return unused ranges back to the db.
Note where we maintained a single global sequence before, different replication streams can now have oeprations "out-of-order" on this global sequence. This is not an issue - we only need to maintain ordering within each individual replication stream.
The pre-allocated ranges also allows future optimizations, since we can now allocate the op_id sequences before we starting writing to the database, allowing for better pipelining of replication work (see #797).
Fencing
Previously, we had two mechanisms to avoid consistency issues in case of multiple concurrent replication jobs on the same stream:
In practice we've never observed cases where those were not sufficient, but it did not provide strong guarantees. Furthermore, the lock on the op_id sequence was global, which is what we want to remove in this PR.
So this replaces the lock on op_id sequence with "fencing" on the replication stream lease: Every write confirms that the replication job still holds the lease.
Details on the fencing implementation and the guarantees it provides are added to a doc.
This PR also contains some db operation restructuring, to ensure that the new fencing implementation does not add significant overhead in terms of db round-trips.
TODO
sync_rules.writer_transaction;sync_rules.last_persisted_op: Do we need them? If yes, what does backwards-compatibility look like?AI Usage
Implemented with Codex gpt-6-astra. Manually checked the approach and reviewed the changes, as well as confirming the performance impact.