Database Administration — Fri Apr 17

← Home | ← database-admin

PostgreSQL - DBA Toolkit - Blocking and Lock Waits

Fri Apr 17 — Find exactly who is blocking who in PostgreSQL — the blocking session, the waiting session, and the query that started the pile-up.
#postgresql #dba #monitoring #blocking #locks #troubleshooting #tool-kit

Someone Is Waiting. You Need to Know Who Started It.

Lock waits in PostgreSQL do not make noise.

An application hangs. Queries pile up behind it. Users report timeouts. And somewhere in the middle of it all, one session is sitting on a lock that nobody released.

This script joins pg_stat_activity with pg_locks to build the full blocking chain — the session doing the blocking, the session waiting, how long it has been waiting, and what each one is actually trying to do.

BlockingandLockWaits.sql
    Loading…
  

Reading the Results

ColumnWhat It Tells You
blocking_pidThe process ID of the session holding the lock
blocking_userThe database user running the blocking session
blocking_queryThe SQL the blocking session is executing (or last executed)
blocked_pidThe process ID of the session waiting for the lock
blocked_userThe database user stuck waiting
blocked_queryThe SQL that cannot proceed
wait_durationHow long the blocked session has been waiting
lock_typeThe type of lock being contested — e.g. relation, tuple, transactionid

What to Watch For

SignalWhat It Means
wait_duration growing over minutesA transaction is open and idle — likely a forgotten BEGIN with no COMMIT
Many blocked sessions, one blocking PIDOne query or transaction is the root cause — kill or investigate that one
blocking_query shows a SELECTRow-level FOR UPDATE or FOR SHARE locking — not always obvious from the query text
lock_type = relationA table-level lock — DDL, TRUNCATE, or LOCK TABLE is involved
Same blocking PID across multiple restartsA long-running transaction that survived a retry — check client-side retry logic
blocking_query is idle in transactionThe session committed or rolled back but held locks — connection pool issue

Killing the Blocker

Once you identify the blocking PID, you have two options:

KillingTheBlocker.sql
    Loading…
  

pg_cancel_backend cancels only the current query. pg_terminate_backend ends the entire connection. Use terminate when the session is idle in transaction and will not respond to cancel.

Gareth Winterman