Skip to content

Commit 8cbc6d1

Browse files
committed
sql/opt: add locking durability
In addition to strength and wait policy, we now add a third property to locks: durability. Locks with `LockDurabilityGuaranteed` are guaranteed to be held until commit (if the transaction commits). Durable locks must be used when correctness depends on locking. This is never the case under our `SERIALIZABLE` isolation, but under `SNAPSHOT` and `READ COMMITTED` isolation it will be the case for `SELECT FOR UPDATE` statements, which will be the first users of durable locks. This commit adds locking durability to the optimizer and `EXPLAIN` output, but does not plumb it into KV yet. It will be used in the next commit to temporarily disallow `SELECT FOR UPDATE` statements under `SNAPSHOT` and `READ COMMITTED` isolation. Release note: None
1 parent 57b3bdf commit 8cbc6d1

File tree

9 files changed

+226
-10
lines changed

9 files changed

+226
-10
lines changed

pkg/sql/catalog/descpb/locking.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ enum ScanLockingStrength {
115115
// on each key scanned.
116116
FOR_UPDATE = 4;
117117
}
118-
118+
119119
// LockingWaitPolicy controls the policy used for handling conflicting locks
120120
// held by other active transactions when attempting to lock rows due to FOR
121121
// UPDATE/SHARE clauses (i.e. it represents the NOWAIT and SKIP LOCKED options).

pkg/sql/opt/exec/execbuilder/mutation.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -973,8 +973,12 @@ func (b *Builder) canAutoCommit(rel memo.RelExpr) bool {
973973

974974
// forUpdateLocking is the row-level locking mode used by mutations during their
975975
// initial row scan, when such locking is deemed desirable. The locking mode is
976-
// equivalent that used by a SELECT ... FOR UPDATE statement.
977-
var forUpdateLocking = opt.Locking{Strength: tree.ForUpdate}
976+
// equivalent to that used by a SELECT FOR UPDATE statement, except not durable.
977+
var forUpdateLocking = opt.Locking{
978+
Strength: tree.ForUpdate,
979+
WaitPolicy: tree.LockWaitBlock,
980+
Durability: tree.LockDurabilityBestEffort,
981+
}
978982

979983
// shouldApplyImplicitLockingToMutationInput determines whether or not the
980984
// builder should apply a FOR UPDATE row-level locking mode to the initial row

pkg/sql/opt/exec/execbuilder/relational.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ func (b *Builder) scanParams(
620620

621621
locking := scan.Locking
622622
if b.forceForUpdateLocking {
623-
locking = forUpdateLocking
623+
locking = locking.Max(forUpdateLocking)
624624
}
625625
b.ContainsNonDefaultKeyLocking = b.ContainsNonDefaultKeyLocking || locking.IsLocking()
626626

@@ -2172,7 +2172,7 @@ func (b *Builder) buildIndexJoin(join *memo.IndexJoinExpr) (execPlan, error) {
21722172

21732173
locking := join.Locking
21742174
if b.forceForUpdateLocking {
2175-
locking = forUpdateLocking
2175+
locking = locking.Max(forUpdateLocking)
21762176
}
21772177
b.ContainsNonDefaultKeyLocking = b.ContainsNonDefaultKeyLocking || locking.IsLocking()
21782178

@@ -2493,7 +2493,7 @@ func (b *Builder) buildLookupJoin(join *memo.LookupJoinExpr) (execPlan, error) {
24932493

24942494
locking := join.Locking
24952495
if b.forceForUpdateLocking {
2496-
locking = forUpdateLocking
2496+
locking = locking.Max(forUpdateLocking)
24972497
}
24982498
b.ContainsNonDefaultKeyLocking = b.ContainsNonDefaultKeyLocking || locking.IsLocking()
24992499

@@ -2735,7 +2735,7 @@ func (b *Builder) buildInvertedJoin(join *memo.InvertedJoinExpr) (execPlan, erro
27352735

27362736
locking := join.Locking
27372737
if b.forceForUpdateLocking {
2738-
locking = forUpdateLocking
2738+
locking = locking.Max(forUpdateLocking)
27392739
}
27402740
b.ContainsNonDefaultKeyLocking = b.ContainsNonDefaultKeyLocking || locking.IsLocking()
27412741

@@ -2816,8 +2816,8 @@ func (b *Builder) buildZigzagJoin(join *memo.ZigzagJoinExpr) (execPlan, error) {
28162816
leftLocking := join.LeftLocking
28172817
rightLocking := join.RightLocking
28182818
if b.forceForUpdateLocking {
2819-
leftLocking = forUpdateLocking
2820-
rightLocking = forUpdateLocking
2819+
leftLocking = leftLocking.Max(forUpdateLocking)
2820+
rightLocking = rightLocking.Max(forUpdateLocking)
28212821
}
28222822
b.ContainsNonDefaultKeyLocking = b.ContainsNonDefaultKeyLocking || leftLocking.IsLocking() || rightLocking.IsLocking()
28232823

0 commit comments

Comments
 (0)