staging-v24.1.29: release-24.1: optbuilder: take FOR SHARE locking during RC FK child checks#169973
Merged
rail merged 3 commits intocockroachdb:staging-v24.1.29from May 8, 2026
Merged
Conversation
|
Thanks for opening a backport. Before merging, please confirm that it falls into one of the following categories (select one):
Add a brief release justification to the PR description explaining your selection. Also, confirm that the change does not break backward compatibility and complies with all aspects of the backport policy. All backports must be reviewed by the TL and EM for the owning area. |
Member
jlinder
approved these changes
May 8, 2026
Previously foreign key cascades would never take locks on the rows they
modified. Under serializable isolation, this presents no difficulty as
locks are purely advisory at that isolation level. However, under
repeatable read and read committed isolations, locks are necessary to
avoid incorrect enforcement.
For example, consider this timing:
t1: R-C statement that deletes from parent starts.
t2: transaction that writes to child commits. This row references the
parent that the previous statement is deleting, but still sees it
because that statement hasn't done anything yet.
t3: R-C statement deletes child keys, but has a timestamp of t1, so
doesn't see the row inserted by t2.
After the R-C transaction commits, we're left with a child table that
has a row it should not. A similar problem exists for update cascades.
Fortunately, the fix is relatively simple. By taking an exclusive lock
on the child rows before we delete or update them, we force the KV
to check write intents. KV will see the write at t2 and either bump
t1's timestamp or force it to restart.
Fixes: cockroachdb#150282
Release note (bug fix): A bug that would allow a race condition in
foreign key cascades under read committed and repeatable read isolations
has been fixed.
In cockroachdb#150291 we added subtest `fk_cascade_race_150282` which exercises FK checks performed by concurrent Serializable and Read Committed transactions. Unfortunately thanks to this test we've discovered that the locking added in cockroachdb#150291 is insufficient for preventing all FK violations. We need to turn on the disabled parent-FK-check locking for the Serializable transaction. This commmit fixes subtest `fk_cascade_race_150282` by turning on these settings for the Serializable transaction: - `enable_implicit_fk_locking_for_serializable` - `enable_shared_locking_for_serializable` - `enable_durable_locking_for_serializable` Informs: cockroachdb#151663 Release note: None
Under Read Committed isolation, we need to take FOR SHARE locking during FK child checks to ensure that the rows read by the FK check have not already been written to at a later timestamp. (This is the same reason that we needed to add FOR UPDATE locking to RC FK cascades in cockroachdb#150291.) Even with this locking, we still need Serializable transactions to have the FK parent locking enabled, if both SSI and RC transactions are going to concurrently modify rows involved in FK relationships. This is because FOR SHARE (and FOR UPDATE) locking does not prevent phantoms. Informs: cockroachdb#151663 Release note (bug fix): A bug that would allow FK violations as a result of some combinations of concurrent Read Committed and Serializable transactions has been fixed. Note that if both Serializable and weaker-isolation transactions will concurrently modify rows involved in FK relationships, the Serializable transactions must have the following session variables set to prevent any possible FK violations: - `SET enable_implicit_fk_locking_for_serializable = on;` - `SET enable_shared_locking_for_serializable = on;` - `SET enable_durable_locking_for_serializable = on;`
905e352 to
f0296aa
Compare
|
Detected infrastructure failure (matched: self-hosted runner lost communication with the server). Automatically rerunning failed jobs. (run link) |
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.
Backport 3/3 commits from #169926.
/cc @cockroachdb/release
Backport 1/1 commits from #150291 and 2/2 commits from #152245.
/cc @cockroachdb/release
opt: take exclusive locks for foreign key cascades under read-committed
Previously foreign key cascades would never take locks on the rows they modified. Under serializable isolation, this presents no difficulty as locks are purely advisory at that isolation level. However, under repeatable read and read committed isolations, locks are necessary to avoid incorrect enforcement.
For example, consider this timing:
t1: R-C statement that deletes from parent starts.
t2: transaction that writes to child commits. This row references the
parent that the previous statement is deleting, but still sees it
because that statement hasn't done anything yet.
t3: R-C statement deletes child keys, but has a timestamp of t1, so
doesn't see the row inserted by t2.
After the R-C transaction commits, we're left with a child table that has a row it should not. A similar problem exists for update cascades.
Fortunately, the fix is relatively simple. By taking an exclusive lock on the child rows before we delete or update them, we force the KV to check write intents. KV will see the write at t2 and either bump t1's timestamp or force it to restart.
Fixes: #150282
Release note (bug fix): A but that would allow a race condition in foreign key cascades under read committed and repeatable read isolations has been fixed.
logictest: fix fk_cascade_race_150282
In #150291 we added subtest
fk_cascade_race_150282which exercises FKchecks performed by concurrent Serializable and Read Committed
transactions. Unfortunately thanks to this test we've discovered that
the locking added in #150291 is insufficient for preventing all FK
violations. We need to turn on the disabled parent-FK-check locking for
the Serializable transaction.
This commmit fixes subtest
fk_cascade_race_150282by turning on thesesettings for the Serializable transaction:
enable_implicit_fk_locking_for_serializableenable_shared_locking_for_serializableenable_durable_locking_for_serializableInforms: #151663
Release note: None
optbuilder: take FOR SHARE locking during RC FK child checks
Under Read Committed isolation, we need to take FOR SHARE locking during
FK child checks to ensure that the rows read by the FK check have not
already been written to at a later timestamp. (This is the same reason
that we needed to add FOR UPDATE locking to RC FK cascades in #150291.)
Even with this locking, we still need Serializable transactions to have
the FK parent locking enabled, if both SSI and RC transactions are going
to concurrently modify rows involved in FK relationships. This is
because FOR SHARE (and FOR UPDATE) locking does not prevent phantoms.
Informs: #151663
Release note (bug fix): A bug that would allow FK violations as a result
of some combinations of concurrent Read Committed and Serializable
transactions has been fixed.
Note that if both Serializable and weaker-isolation transactions will
concurrently modify rows involved in FK relationships, the Serializable
transactions must have the following session variables set to prevent
any possible FK violations:
SET enable_implicit_fk_locking_for_serializable = on;SET enable_shared_locking_for_serializable = on;SET enable_durable_locking_for_serializable = on;Release justification: fix for serious FK violation issue.
Release justification: