Skip to content

Commit

Permalink
sql: introduce crdb_internal.cluster_locks virtual table
Browse files Browse the repository at this point in the history
This change introduces the new virtual table
`crdb_internal.cluster_locks`, as proposed in the KV Lock Observability
RFC (#75541), to expose lock contention.  This virtual table displays
the locks currently tracked in the lock tables in ranges across a
cluster, utilizing the KV `QueryLocksRequest` API to gather information
on the lock holders as well as the operations waiting on the locks
before converting to a user-friendly SQL view that incorporates
information about the database, table, schema, and index.

For example,
```
root@localhost:26261/defaultdb> select range_id, table_name, lock_key_pretty, txn_id, ts, lock_strength, durability, granted, contended, duration from crdb_internal.cluster_locks;
  range_id | table_name |     lock_key_pretty      |                txn_id                |             ts             | lock_strength | durability | granted | contended |    duration
-----------+------------+--------------------------+--------------------------------------+----------------------------+---------------+------------+---------+-----------+------------------
       235 | kv         | /Table/115/1/"alex"/0    | 7471e67b-bbc3-4dd9-a42f-43ec97949b14 | 2022-03-26 00:23:45.916745 | Exclusive     | Replicated |  true   |   true    | 00:01:50.607386
       235 | kv         | /Table/115/1/"alex"/0    | d71ea8eb-21b9-48a0-98b6-82eed84ed76f | 2022-03-26 00:24:02.137125 | None          | Replicated |  false  |   true    | 00:01:50.607376
       235 | kv         | /Table/115/1/"bob"/0     | 7471e67b-bbc3-4dd9-a42f-43ec97949b14 | 2022-03-26 00:23:45.916745 | Exclusive     | Replicated |  true   |   false   | 00:01:50.607384
       235 | kv         | /Table/115/1/"chris"/0   | 7471e67b-bbc3-4dd9-a42f-43ec97949b14 | 2022-03-26 00:23:45.916745 | Exclusive     | Replicated |  true   |   false   | 00:01:50.607383
       255 | kv         | /Table/115/1/"lauren"/0  | 7471e67b-bbc3-4dd9-a42f-43ec97949b14 | 2022-03-26 00:23:45.819704 | Exclusive     | Replicated |  true   |   true    | 00:01:50.607757
       255 | kv         | /Table/115/1/"lauren"/0  | d71ea8eb-21b9-48a0-98b6-82eed84ed76f | 2022-03-26 00:24:02.137125 | None          | Replicated |  false  |   true    | 00:01:50.60773
       255 | kv         | /Table/115/1/"marilyn"/0 | 7471e67b-bbc3-4dd9-a42f-43ec97949b14 | 2022-03-26 00:23:45.819704 | Exclusive     | Replicated |  true   |   false   | 00:01:50.607755
       255 | kv         | /Table/115/1/"mike"/0    | 7471e67b-bbc3-4dd9-a42f-43ec97949b14 | 2022-03-26 00:23:45.819704 | Exclusive     | Replicated |  true   |   false   | 00:01:50.607754
       255 | kv         | /Table/115/1/"nancy"/0   | 7471e67b-bbc3-4dd9-a42f-43ec97949b14 | 2022-03-26 00:23:45.819704 | Exclusive     | Replicated |  true   |   false   | 00:01:50.607745
       255 | kv         | /Table/115/1/"noah"/0    | 7471e67b-bbc3-4dd9-a42f-43ec97949b14 | 2022-03-26 00:23:45.819704 | Exclusive     | Replicated |  true   |   false   | 00:01:50.607744
       255 | kv         | /Table/115/1/"paul"/0    | 7471e67b-bbc3-4dd9-a42f-43ec97949b14 | 2022-03-26 00:23:45.819704 | Exclusive     | Replicated |  true   |   false   | 00:01:50.607744
       255 | kv         | /Table/115/1/"peter"/0   | 7471e67b-bbc3-4dd9-a42f-43ec97949b14 | 2022-03-26 00:23:45.819704 | Exclusive     | Replicated |  true   |   false   | 00:01:50.607743
       256 | kv         | /Table/115/1/"sam"/0     | 7471e67b-bbc3-4dd9-a42f-43ec97949b14 | 2022-03-26 00:23:45.740235 | Exclusive     | Replicated |  true   |   true    | 00:01:50.607582
       256 | kv         | /Table/115/1/"sam"/0     | d71ea8eb-21b9-48a0-98b6-82eed84ed76f | 2022-03-26 00:24:02.137125 | None          | Replicated |  false  |   true    | 00:01:50.607573
       256 | kv         | /Table/115/1/"thomas"/0  | 7471e67b-bbc3-4dd9-a42f-43ec97949b14 | 2022-03-26 00:23:45.740235 | Exclusive     | Replicated |  true   |   false   | 00:01:50.607581
       256 | kv         | /Table/115/1/"zebra"/0   | 7471e67b-bbc3-4dd9-a42f-43ec97949b14 | 2022-03-26 00:23:45.740235 | Exclusive     | Replicated |  true   |   false   | 00:01:50.60758
(16 rows)
```

This internal table is usable for system tenants as well as secondary
tenants.  It is also useful in conjunction with other
`crdb_internal.cluster_*` tables used for observability, and also can be
joined with itself to visualize blocked operations, and the transactions
that are blocking them.  This feature is gated on v22.1, to ensure that
older nodes will not receive `kv.Batch` requests with
`QueryLocksRequest`s in them.

Closes #74834

Release justification: Low risk, high benefit change.

Release note (sql change): introducing the `crdb_internal.cluster_locks`
virtual table, which exposes the current state of locks on keys tracked
by concurrency control. The virtual table displays metadata on locks
currently held by transactions, as well as operations waiting to obtain
the locks, and as such can be used to visualize active contention.
The `VIEWACTIVITY` or `VIEWACTIVITYREDACTED` role option, or the
`admin` role, is required to access the virtual table; however, if the
user only has the `VIEWACTIVITYREDACTED` role option, the key on which
a lock is held will be redacted.
  • Loading branch information
AlexTalks committed Apr 22, 2022
1 parent 6c4c32c commit b3096b8
Show file tree
Hide file tree
Showing 13 changed files with 2,585 additions and 1,761 deletions.
264 changes: 264 additions & 0 deletions pkg/ccl/logictestccl/testdata/logic_test/cluster_locks_tenant
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
# LogicTest: 3node-tenant

# Create a table, write a row, lock it, then switch users.
statement ok
CREATE TABLE t (k STRING PRIMARY KEY, v STRING, FAMILY (k,v))

statement ok
GRANT ALL ON t TO testuser

statement ok
INSERT INTO t VALUES ('a', 'val1'), ('b', 'val2'), ('c', 'val3'), ('l', 'val4'), ('m', 'val5'), ('p', 'val6'), ('s', 'val7'), ('t', 'val8'), ('z', 'val9')

# Also create an additional user with VIEWACTIVITYREDACTED, with only permissions on t
statement ok
CREATE USER testuser2 WITH VIEWACTIVITYREDACTED

statement ok
GRANT ALL ON t TO testuser2

statement ok
CREATE TABLE t2 (k STRING PRIMARY KEY, v STRING, FAMILY (k,v))

statement ok
INSERT INTO t2 VALUES ('a', 'val1'), ('b', 'val2')

# Start txn1 where we acquire replicated locks
statement ok
BEGIN PRIORITY HIGH

statement ok
UPDATE t SET v = '_updated' WHERE k >= 'b' AND k < 'x'

let $root_session
SHOW session_id

user testuser

let $testuser_session
SHOW session_id

statement ok
BEGIN

# switch back to root, collect data needed for validation
user root

let $txn1
SELECT txns.id FROM crdb_internal.cluster_transactions txns WHERE txns.session_id = '$root_session'

let $txn2
SELECT txns.id FROM crdb_internal.cluster_transactions txns WHERE txns.session_id = '$testuser_session'

user testuser

query TT async,rowsort readReq
SELECT * FROM t
----
a val1
b _updated
c _updated
l _updated
m _updated
p _updated
s _updated
t _updated
z val9

user root

query TTT colnames,retry
SELECT user_name, query, phase FROM crdb_internal.cluster_queries WHERE txn_id='$txn2'
----
user_name query phase
testuser SELECT * FROM t executing

# looking at each transaction separately, validate the expected results in the lock table
query TTTTTTBB colnames,retry
SELECT database_name, schema_name, table_name, lock_key_pretty, lock_strength, durability, granted, contended FROM crdb_internal.cluster_locks WHERE table_name='t' AND txn_id='$txn1'
----
database_name schema_name table_name lock_key_pretty lock_strength durability granted contended
test public t /Table/106/1/"b"/0 Exclusive Replicated true true
test public t /Table/106/1/"c"/0 Exclusive Replicated true false
test public t /Table/106/1/"l"/0 Exclusive Replicated true false
test public t /Table/106/1/"m"/0 Exclusive Replicated true false
test public t /Table/106/1/"p"/0 Exclusive Replicated true false
test public t /Table/106/1/"s"/0 Exclusive Replicated true false
test public t /Table/106/1/"t"/0 Exclusive Replicated true false

query TTTTTTBB colnames
SELECT database_name, schema_name, table_name, lock_key_pretty, lock_strength, durability, granted, contended FROM crdb_internal.cluster_locks WHERE table_name='t' AND txn_id='$txn2'
----
database_name schema_name table_name lock_key_pretty lock_strength durability granted contended
test public t /Table/106/1/"b"/0 None Replicated false true

# check that we can't see keys, potentially revealing PII, with VIEWACTIVITYREDACTED
user testuser2

query TTTTTTBB colnames
SELECT database_name, schema_name, table_name, lock_key_pretty, lock_strength, durability, granted, contended FROM crdb_internal.cluster_locks WHERE table_name='t' AND txn_id='$txn1'
----
database_name schema_name table_name lock_key_pretty lock_strength durability granted contended
test public t · Exclusive Replicated true true
test public t · Exclusive Replicated true false
test public t · Exclusive Replicated true false
test public t · Exclusive Replicated true false
test public t · Exclusive Replicated true false
test public t · Exclusive Replicated true false
test public t · Exclusive Replicated true false

user root

query I
SELECT count(*) FROM crdb_internal.cluster_locks WHERE table_name = 't'
----
8

statement ok
COMMIT

query I retry
SELECT count(*) FROM crdb_internal.cluster_locks WHERE table_name = 't'
----
0

user testuser

awaitquery readReq

statement ok
COMMIT

user root

# start txn3
statement ok
BEGIN

user testuser

# start txn4
statement ok
BEGIN

user root

query TT rowsort
SELECT * FROM t FOR UPDATE
----
a val1
b _updated
c _updated
l _updated
m _updated
p _updated
s _updated
t _updated
z val9

let $txn3
SELECT txns.id FROM crdb_internal.cluster_transactions txns WHERE txns.session_id = '$root_session'

let $txn4
SELECT txns.id FROM crdb_internal.cluster_transactions txns WHERE txns.session_id = '$testuser_session'

user testuser

statement async deleteReq count 7
DELETE FROM t WHERE k >= 'b' AND k < 'x'

user root

query TTT colnames,retry
SELECT user_name, query, phase FROM crdb_internal.cluster_queries WHERE txn_id='$txn4'
----
user_name query phase
testuser DELETE FROM t WHERE (k >= 'b') AND (k < 'x') executing

# looking at each transaction separately, validate the expected results in the lock table
query TTTTTTBB colnames,retry
SELECT database_name, schema_name, table_name, lock_key_pretty, lock_strength, durability, granted, contended FROM crdb_internal.cluster_locks WHERE table_name='t' AND txn_id='$txn3'
----
database_name schema_name table_name lock_key_pretty lock_strength durability granted contended
test public t /Table/106/1/"a"/0 Exclusive Unreplicated true false
test public t /Table/106/1/"b"/0 Exclusive Unreplicated true true
test public t /Table/106/1/"c"/0 Exclusive Unreplicated true false
test public t /Table/106/1/"l"/0 Exclusive Unreplicated true false
test public t /Table/106/1/"m"/0 Exclusive Unreplicated true false
test public t /Table/106/1/"p"/0 Exclusive Unreplicated true false
test public t /Table/106/1/"s"/0 Exclusive Unreplicated true false
test public t /Table/106/1/"t"/0 Exclusive Unreplicated true false
test public t /Table/106/1/"z"/0 Exclusive Unreplicated true false

query TTTTTTBB colnames
SELECT database_name, schema_name, table_name, lock_key_pretty, lock_strength, durability, granted, contended FROM crdb_internal.cluster_locks WHERE table_name='t' AND txn_id='$txn4'
----
database_name schema_name table_name lock_key_pretty lock_strength durability granted contended
test public t /Table/106/1/"b"/0 Exclusive Unreplicated false true

query I
SELECT count(*) FROM crdb_internal.cluster_locks WHERE table_name = 't'
----
10

statement ok
ROLLBACK

user testuser

awaitstatement deleteReq

statement ok
COMMIT

user root

query I retry
SELECT count(*) FROM crdb_internal.cluster_locks WHERE table_name = 't'
----
0

# validate that only locks on keys in privileged tables can be seen
statement ok
BEGIN

query TT rowsort
SELECT * FROM t FOR UPDATE
----
a val1
z val9

query TT rowsort
SELECT * FROM t2 FOR UPDATE
----
a val1
b val2

query I retry
SELECT count(*) FROM crdb_internal.cluster_locks WHERE table_name IN ('t','t2')
----
4

user testuser

query error pq: user testuser does not have VIEWACTIVITY or VIEWACTIVITYREDACTED privilege
SELECT database_name, schema_name, table_name, lock_key_pretty, lock_strength, durability, granted, contended FROM crdb_internal.cluster_locks

user testuser2

query TTTTTTBB colnames
SELECT database_name, schema_name, table_name, lock_key_pretty, lock_strength, durability, granted, contended FROM crdb_internal.cluster_locks WHERE table_name IN ('t', 't2')
----
database_name schema_name table_name lock_key_pretty lock_strength durability granted contended
test public t · Exclusive Unreplicated true false
test public t · Exclusive Unreplicated true false

user root

statement ok
ROLLBACK

query I retry
SELECT count(*) FROM crdb_internal.cluster_locks WHERE table_name IN ('t','t2')
----
0
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ crdb_internal cluster_contention_events table NULL NULL NULL
crdb_internal cluster_database_privileges table NULL NULL NULL
crdb_internal cluster_distsql_flows table NULL NULL NULL
crdb_internal cluster_inflight_traces table NULL NULL NULL
crdb_internal cluster_locks table NULL NULL NULL
crdb_internal cluster_queries table NULL NULL NULL
crdb_internal cluster_sessions table NULL NULL NULL
crdb_internal cluster_settings table NULL NULL NULL
Expand Down
1 change: 1 addition & 0 deletions pkg/cli/zip_cluster_wide.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ var debugZipTablesPerCluster = []string{
"crdb_internal.cluster_contention_events",
"crdb_internal.cluster_distsql_flows",
"crdb_internal.cluster_database_privileges",
"crdb_internal.cluster_locks",
"crdb_internal.cluster_queries",
"crdb_internal.cluster_sessions",
"crdb_internal.cluster_settings",
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ go_library(
"//pkg/kv/kvclient/kvtenant",
"//pkg/kv/kvclient/rangecache",
"//pkg/kv/kvclient/rangefeed",
"//pkg/kv/kvserver/concurrency/lock",
"//pkg/kv/kvserver/kvserverbase",
"//pkg/kv/kvserver/liveness/livenesspb",
"//pkg/kv/kvserver/protectedts",
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/catalog/catconstants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ const (
CrdbInternalClusterContendedTablesViewID
CrdbInternalClusterContentionEventsTableID
CrdbInternalClusterDistSQLFlowsTableID
CrdbInternalClusterLocksTableID
CrdbInternalClusterQueriesTableID
CrdbInternalClusterTransactionsTableID
CrdbInternalClusterSessionsTableID
Expand Down
Loading

0 comments on commit b3096b8

Please sign in to comment.