forked from cockroachdb/cockroach
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
kv/concurrency: drop uncontended replicated lock on unreplicated upgrade
Fixes cockroachdb#49658. Informs cockroachdb#9521. Informs cockroachdb#49973. Related to cockroachdb#49684. This commit tweaks the `lockTable`'s handling of lock acquisition to drop write-uncontended locks when upgraded from the Unreplicated to Replicated durability in much the same way we drop Replicated locks when first acquired. This is possible because a Replicated lock is also stored as an MVCC intent, so it does not need to also be stored in the lockTable if writers are not queuing on it. This is beneficial because it serves as a mitigation for cockroachdb#49973 and avoids the 99th percentile latency regression observed in cockroachdb#49658. Since we aren't currently great at avoiding excessive contention on limited scans when locks are in the lockTable, it's better the keep locks out of the lockTable when possible. If any of the readers do truly contend with this lock even after their limit has been applied, they will notice during their MVCC scan and re-enter the queue (possibly recreating the lock through AddDiscoveredLock). Still, in practice this seems to work well in avoiding most of the artificial concurrency discussed in cockroachdb#49973. It's a bit of a hack and I am very interested in fixing this fully in the future (through an approach like cockroachdb#33373 or by incrementally consulting the lockTable in a `lockAwareIterator`), but for now, I don't see a downside to make this change. I intend to backport this change to v20.1, as it's causing issues in one of the demos we like to run. Release note (performance improvement): limited SELECT statements now do a better job avoiding unnecessary contention with UPDATE and SELECT FOR UPDATE statements.
- Loading branch information
1 parent
5e0cecf
commit 03b374a
Showing
5 changed files
with
293 additions
and
35 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
129 changes: 129 additions & 0 deletions
129
pkg/kv/kvserver/concurrency/testdata/lock_table/lock_dropped
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
# Misc tests where locks are ignored or dropped during lock acquisitions. | ||
|
||
new-lock-table maxlocks=10000 | ||
---- | ||
|
||
# --------------------------------------------------------------------------------- | ||
# New replicated locks are ignored. | ||
# --------------------------------------------------------------------------------- | ||
|
||
new-txn txn=txn1 ts=10 epoch=0 seq=2 | ||
---- | ||
|
||
new-request r=req1 txn=txn1 ts=10 spans=w@a | ||
---- | ||
|
||
acquire r=req1 k=a durability=r | ||
---- | ||
global: num=0 | ||
local: num=0 | ||
|
||
# --------------------------------------------------------------------------------- | ||
# Upgrading from unreplicated to replicated for an uncontended lock causes that | ||
# lock to be dropped. | ||
# --------------------------------------------------------------------------------- | ||
|
||
acquire r=req1 k=a durability=u | ||
---- | ||
global: num=1 | ||
lock: "a" | ||
holder: txn: 00000000-0000-0000-0000-000000000001, ts: 0.000000010,0, info: unrepl epoch: 0, seqs: [2] | ||
local: num=0 | ||
|
||
acquire r=req1 k=a durability=r | ||
---- | ||
global: num=0 | ||
local: num=0 | ||
|
||
# --------------------------------------------------------------------------------- | ||
# Upgrading from unreplicated to replicated for a lock with only waiting readers | ||
# causes that lock to be dropped and the readers to be released. | ||
# --------------------------------------------------------------------------------- | ||
|
||
new-request r=reqContendReader txn=none ts=10 spans=r@a | ||
---- | ||
|
||
acquire r=req1 k=a durability=u | ||
---- | ||
global: num=1 | ||
lock: "a" | ||
holder: txn: 00000000-0000-0000-0000-000000000001, ts: 0.000000010,0, info: unrepl epoch: 0, seqs: [2] | ||
local: num=0 | ||
|
||
scan r=reqContendReader | ||
---- | ||
start-waiting: true | ||
|
||
---- | ||
global: num=1 | ||
lock: "a" | ||
holder: txn: 00000000-0000-0000-0000-000000000001, ts: 0.000000010,0, info: unrepl epoch: 0, seqs: [2] | ||
waiting readers: | ||
req: 1, txn: none | ||
distinguished req: 1 | ||
local: num=0 | ||
|
||
acquire r=req1 k=a durability=r | ||
---- | ||
global: num=0 | ||
local: num=0 | ||
|
||
guard-state r=reqContendReader | ||
---- | ||
new: state=doneWaiting | ||
|
||
# --------------------------------------------------------------------------------- | ||
# Upgrading from unreplicated to replicated for a lock with waiting reader and | ||
# writers causes the lock to be retained. | ||
# --------------------------------------------------------------------------------- | ||
|
||
new-request r=reqContendWriter txn=none ts=10 spans=w@a | ||
---- | ||
|
||
acquire r=req1 k=a durability=u | ||
---- | ||
global: num=1 | ||
lock: "a" | ||
holder: txn: 00000000-0000-0000-0000-000000000001, ts: 0.000000010,0, info: unrepl epoch: 0, seqs: [2] | ||
local: num=0 | ||
|
||
scan r=reqContendReader | ||
---- | ||
start-waiting: true | ||
|
||
scan r=reqContendWriter | ||
---- | ||
start-waiting: true | ||
|
||
---- | ||
global: num=1 | ||
lock: "a" | ||
holder: txn: 00000000-0000-0000-0000-000000000001, ts: 0.000000010,0, info: unrepl epoch: 0, seqs: [2] | ||
waiting readers: | ||
req: 1, txn: none | ||
queued writers: | ||
active: true req: 2, txn: none | ||
distinguished req: 1 | ||
local: num=0 | ||
|
||
acquire r=req1 k=a durability=r | ||
---- | ||
global: num=1 | ||
lock: "a" | ||
holder: txn: 00000000-0000-0000-0000-000000000001, ts: 0.000000010,0, info: repl epoch: 0, seqs: [2], unrepl epoch: 0, seqs: [2] | ||
waiting readers: | ||
req: 1, txn: none | ||
queued writers: | ||
active: true req: 2, txn: none | ||
distinguished req: 1 | ||
local: num=0 | ||
|
||
guard-state r=reqContendReader | ||
---- | ||
new: state=waitForDistinguished txn=txn1 key="a" held=true guard-access=read | ||
|
||
guard-state r=reqContendWriter | ||
---- | ||
new: state=waitFor txn=txn1 key="a" held=true guard-access=write |
Oops, something went wrong.