Diagnostic Queries
Symptoms
A statement (often using NOWAIT) could not immediately acquire the lock it needed on a relation because another session holds a conflicting lock. PostgreSQL raises SQLSTATE 55P03 (lock_not_available).
- Typical with
SELECT … FOR UPDATE NOWAITorLOCK TABLE … NOWAIT. - The command fails immediately rather than waiting.
- Indicates contention on the named relation.
What the server log shows
ERROR: could not obtain lock on relation "orders"
Why PostgreSQL raises this — what the manual says
the LOCK reference (Parameters):
“If NOWAIT is specified, LOCK TABLE does not wait to acquire the desired lock: if it cannot be acquired immediately, the command is aborted and an error is emitted.”
With NOWAIT, PostgreSQL attempts to take the lock once. If a conflicting lock is held, it does not block; instead it aborts the statement with 55P03 so the caller can react immediately.
Common causes
- Another transaction holds a conflicting lock on the relation.
- Using NOWAIT to avoid blocking.
- Long-running transactions retaining locks.
How to fix it
- Retry after the conflicting transaction commits/rolls back.
- Identify the blocker via
pg_blocking_pids()and resolve it. - Drop NOWAIT (or set a
lock_timeout) if some waiting is acceptable.
Diagnostic query
-- Who holds conflicting locks?
SELECT pid, mode, relation::regclass, granted
FROM pg_locks WHERE relation = 'orders'::regclass;
Related & next steps
Reference: PostgreSQL 18 — LOCK.
Thanks — noted. This helps keep the database accurate.