locks: lock waits
Captured on 2026-09-27 (UTC+08) on a local KingbaseES V008R006C009B0014 primary and standby, database test, using ~/kbdiag built from Go source commit 93bf65d (static linux/amd64 binary). This is lab evidence, not production validation. The lock waits were created by fault-injection scripts. On the primary, 1045715 holds an exclusive lock on table kbdiag_inj_lock idle in transaction and 1045724 waits for it. A prepared (two-phase) transaction holds a lock on kbdiag_inj_2pc, and 1046007 waits for that. PIDs, counts and timings belong to this capture only.
Usage
| Option | Effect |
|---|---|
--limit N | Show at most N waiting sessions; default 50, 0 for all |
--lock-wait-warn SECONDS | WARN when waiting for a lock longer than this; default 10 |
--json | Print JSON |
Connection options are the same as for sessions. --limit only cuts the waiting list; the findings always cover every wait.
Sessions waiting for locks
blockerscomes first, because the first question in an incident is who is blocking. One blocker often holds up dozens of sessions, so they are sorted by how many sessions they block.holdsis what the blocker holds on the objects its waiters want.- A prepared transaction belongs to no session, so it is shown as
2PC. Its finding says so and points atkbdiag txn, which gives its gid and age. - A blocker that is itself waiting is marked
(queued ahead for ...): the server counts a conflicting session queued earlier as a blocker too. waitinglists every session waiting for a lock, longest wait first.blocked bynames the direct blockers only. For a longer chain, runsessionon the blocker in turn.- Each waiting session over
--lock-wait-warngets onelock.waitingfinding. Shorter waits are listed but not flagged. waitedis measured from the waiter’s last state change: V8R6 has no lock-wait start time. It can overstate the wait a little, never understate it.
A 10-second lock wait is already an incident for OLTP but can be normal for a batch job, so it is a WARN, not a FAIL. 10 seconds filters out passing row-lock contention. Batch databases may want it higher.
With no waits:
On a standby
A session-level advisory lock, taken on the standby:
A lock with no table, such as an advisory lock, shows its lock type as the object.
Insufficient privilege
Connect as kbdiag_ro, which has no monitoring role, while the waits on the primary are still there:
- The locks and who blocks whom are visible. This account cannot see other sessions’ timestamps, so the waits show
?and the threshold cannot be checked. The verdict is UNKNOWN, exit code 3. - Grant
sys_monitorto see everything.
JSON
--json lists the lock rows of the waiting sessions, plus the blockers’ locks on the same objects: pid, locktype, relation, mode, granted, wait_s and blocked_by. blocked_by keeps the server’s raw list: a prepared transaction appears as 0.
Limits
- Parallel query workers have their own PIDs and lock rows, so one waiting parallel query may count as several blocked sessions.
- Several advisory locks of one blocker are listed together in its
holds, since only the lock type is compared.
Exit codes
| Code | Meaning |
|---|---|
| 0 | OK |
| 1 | WARN: a session waited for a lock too long |
| 3 | UNKNOWN: data not collected or not visible |
| 64 | Usage error |
| 69 | Cannot connect |