Repository navigation
fix(masking): a key rotation's swap takes the view first, as a masked read does - #230
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
… read does It renamed the shadow, then replaced the view, while a masked read locks the view, then the shadow: a read arriving between the two deadlocked with it. The view is now replaced first, reading the new shadow by oid.
SauravYadav12
force-pushed
the
fix/mask-rotate-deadlock
branch
from
November 11, 2026 17:35
cb8585b to
1a14abd
Compare
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Fixes a deadlock between
fox mask key rotateand a masked account reading during the rotation. It was seen once in the integration suite: the masked reader got 4deadlock detectederrors.Cause
Each rotated table ends with a swap transaction,
rekeyTable'sSwap. The swap paused writes on the base table, renamed the old shadow table and then the new one (an exclusive lock on the shadow), and replaced the masked view last (an exclusive lock on the view). A masked read locks the view first, then the base table and the shadow.A read arriving between the swap's renames and its view replacement held the view and waited for the shadow, while the swap held the shadow and waited for the view. Postgres ended one of them.
Fix
The swap now replaces the view first, pointed at the new shadow under its
__nextname, and does the renames after. That is the order a read takes its locks in. A view holds its tables by OID, so it keeps reading the new shadow once it's renamed into place. A read arriving mid-swap now waits briefly and reads the new masks.Tests