session: one session
Captured on 2026-09-27 (UTC+08) on a local KingbaseES V008R006C009B0014 primary, database test, using ~/kbdiag built from Go source commit 93bf65d (static linux/amd64 binary). This is lab evidence, not production validation. The sessions in the examples were created by fault-injection scripts: 1045715 holds an exclusive lock on table kbdiag_inj_lock idle in transaction, 1045724 waits for it, and 1045809 is a second session idle in transaction. PIDs, counts and timings belong to this capture only.
Usage
| Option | Effect |
|---|---|
<pid> | PID of the session to show; required |
--lock-wait-warn SECONDS | WARN when waiting for a lock longer than this; default 10 |
--idle-in-txn-warn SECONDS | WARN when idle in transaction longer than this; default 300 |
--json | Print JSON |
Connection options are the same as for sessions. The thresholds and findings are the same as those of sessions and locks.
A session waiting for a lock
- The block at the top says who the session is (user, database, application, client, type) and what it does: its state and how long it has been in it, the transaction and statement ages, the wait event, and its transaction id and snapshot xmin.
sqlis the statement in full, with its line breaks. This is the only command that shows the whole SQL. For an idle session the heading readslast sql, since that statement has finished.waiting foris the lock it wants, how long it has waited and who blocks it directly.- It has waited 35 seconds, over the default 10, so there is a
lock.waitingWARN and the exit code is 1. Theverifyline points at the blocker. waitedis measured from the session’s last state change, so it can overstate the wait a little, never understate it.
The blocking session
blockinglists the sessions waiting for locks this session holds.holdslists its locks.- Every transaction holds its own
virtualxidandtransactionidlocks; they are left out ofholdsunless someone waits for a lock of that type. The xid is in the block at the top. - A row lock is labelled with its type, for example
public.t (tuple), so it is not read as a table lock. - The WARN is the waiter’s
lock.waiting: it says this session has been blocking another for 34 seconds, which is this session’s problem. It has noverifyline, since it would point back here. - The session has been idle in transaction for 34 seconds: it took the lock and never committed. Its own
session.idle_in_txnwould come at 300 seconds.
Idle in transaction
With the threshold lowered to 10 seconds:
The session has a transaction id but holds no lock others want, so holds is empty. What it holds back is the vacuum horizon; see txn.
Insufficient privilege
Connect as kbdiag_ro, which has no monitoring role, and look at the blocker:
- User, database and application are visible, and so are the transaction id and xmin. State, times, client, type, wait and SQL show
?. - Locks and who blocks whom are visible; how long the other session has waited is not.
- The session cannot be judged, so the verdict is UNKNOWN with exit code 3. Grant
sys_monitorto see everything.
No such session
When the PID is not found (it may have ended), a note goes to standard error, the verdict is UNKNOWN and the exit code 3. Omitting the PID is a usage error, exit code 64.
JSON
--json carries the activity row and the lock rows the text is built from, with raw values: times in seconds and every lock row, including virtualxid. The lock.waiting finding of the waiter above, with the fields scripts can use:
Exit codes
| Code | Meaning |
|---|---|
| 0 | OK |
| 1 | WARN: a lock wait or idle in transaction over its threshold |
| 3 | UNKNOWN: no such session, or data not collected or not visible |
| 64 | Usage error |
| 69 | Cannot connect |