Diagnostic Queries
Symptoms
A SELECT … FOR UPDATE NOWAIT (or similar) could not immediately acquire a row lock because another transaction holds it. PostgreSQL raises SQLSTATE 55P03 (lock_not_available).
- A NOWAIT lock request failed instantly.
- Another transaction holds the conflicting lock.
- NOWAIT means “fail rather than wait”.
What the server log shows
ERROR: could not obtain lock on row in relation "orders"
Why PostgreSQL raises this — what the manual says
the SELECT reference (The Locking Clause):
“With NOWAIT, the statement reports an error, rather than waiting, if a selected row cannot be locked immediately.”
NOWAIT tells PostgreSQL to fail immediately rather than block when a row is already locked. If the lock is held by another transaction, the request cannot succeed at once, so PostgreSQL reports 55P03.
Common causes
- Another transaction holds a conflicting row lock.
- Contention on hot rows under concurrency.
- Using NOWAIT in a polling/optimistic pattern.
How to fix it
- Retry later, or use
SKIP LOCKEDto process available rows instead. - Reduce lock-hold time in competing transactions.
- Drop
NOWAIT(or use a lock timeout) if waiting briefly is acceptable.
Related & next steps
Reference: PostgreSQL 18 — SELECT.
Thanks — noted. This helps keep the database accurate.