The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Lock rows in key order | SELECT id
FROM app.accounts
WHERE id = ANY (ARRAY[41,72])
ORDER BY id FOR
UPDATE; | View examples |
| Lock a table explicitly | LOCK TABLE app.ledger IN SHARE ROW EXCLUSIVE MODE; | View examples |
| Inspect deadlock delay | SHOW deadlock_timeout; | View examples |
| Set transaction-local lock timeout | SET LOCAL lock_timeout = '2s'; | View examples |
| Disable the lock timeout | SET LOCAL lock_timeout = '0'; | View examples |
| Set a statement timeout | SET LOCAL statement_timeout = '30s'; | View examples |
| Set a role default | ALTER ROLE report_user SET statement_timeout = '30s'; | View examples |
| Inspect the timeout | SHOW statement_timeout; | View examples |
| Bound idle transactions | SET idle_in_transaction_session_timeout = '60s'; | View examples |
| Bound a transaction | SET transaction_timeout = '5min'; | View examples |
| Find blocking PIDs | SELECT pg_blocking_pids(12345); | View examples |
| List lock waiters | SELECT pid, wait_event, query
FROM pg_stat_activity
WHERE wait_event_type = 'Lock'; | View examples |
| Inspect held locks | SELECT * FROM pg_locks WHERE pid = 12345; | View examples |
| Cancel a backend query | SELECT pg_cancel_backend(12345); | View examples |
| Terminate a backend | SELECT pg_terminate_backend(12345, 5000); | View examples |
| Inspect lock-wait logging | SHOW log_lock_waits; | View examples |
| Inspect active transaction age | SELECT pid, xact_start, state
FROM pg_stat_activity
WHERE xact_start IS NOT NULL
ORDER BY xact_start; | View examples |
PostgreSQL detects true deadlocks and aborts one participant, but ordinary blocking can wait indefinitely unless applications set explicit budgets. Reliable systems acquire resources consistently, keep transactions short, distinguish statement cancellation from session termination, and retry only whole idempotent transactions.
Step by step
Detailed examples
Acquire resources in a consistent order
Deadlocks arise from cycles of incompatible locks, including row, table, advisory, and transaction-ID waits. PostgreSQL chooses one transaction as the victim; applications should avoid cycles by sorting keys and acquiring the strongest needed locks consistently. A retry must replay the entire transaction because its prior work was rolled back.
BEGIN;
SELECT id FROM app.accounts
WHERE id IN (41, 72)
ORDER BY id
FOR UPDATE;
UPDATE app.accounts SET balance = balance - 100 WHERE id = 41;
UPDATE app.accounts SET balance = balance + 100 WHERE id = 72;
COMMIT; Note: All code paths touching these accounts must use the same ordering for the convention to work.
Bound time spent waiting for locks
lock_timeout applies only while acquiring a lock, not while executing afterward. A zero value disables it. Set it below statement_timeout when both are used, otherwise the broader statement timeout usually fires first and the lock-specific signal adds no value.
BEGIN;
SET LOCAL lock_timeout = '2s';
ALTER TABLE app.orders ADD COLUMN fulfilled_at timestamptz;
COMMIT; Note: Failure cancels the statement and leaves the transaction aborted; rollback and reschedule rather than looping aggressively.
Give server statements an execution budget
statement_timeout measures from command arrival until completion; in extended-query protocol it applies per query-related message. A timeout cancels the current statement, not the connection. Setting it globally in postgresql.conf can disrupt maintenance and replication roles, so prefer role, database, or transaction scopes.
BEGIN READ ONLY;
SET LOCAL statement_timeout = '30s';
SELECT tenant_id, sum(total) FROM app.orders GROUP BY tenant_id;
COMMIT; Terminate abandoned transactions and sessions
idle_in_transaction_session_timeout ends sessions that sit idle inside a transaction, releasing locks and preventing vacuum horizons from being pinned. idle_session_timeout targets sessions outside a transaction but may interact poorly with poolers. PostgreSQL 18 transaction_timeout bounds a transaction from its start; if it is shorter than or equal to statement_timeout or idle_in_transaction_session_timeout, PostgreSQL ignores that longer timeout. Prepared transactions are exempt.
ALTER ROLE app_user SET idle_in_transaction_session_timeout = '60s';
ALTER ROLE app_user SET transaction_timeout = '5min'; Note: Test pool behavior first; settings affect new sessions and termination discards session state.
Build wait graphs from supported monitoring functions
pg_stat_activity shows current activity and wait events; pg_blocking_pids returns sessions blocking a PID, including prepared transactions represented by zero. Repeatedly querying the views gives only snapshots. Access to other sessions query text is restricted unless the role has suitable monitoring privileges.
SELECT a.pid, a.usename, a.wait_event_type, a.wait_event,
pg_blocking_pids(a.pid) AS blocking_pids,
clock_timestamp() - a.query_start AS query_age, a.query
FROM pg_stat_activity a
WHERE cardinality(pg_blocking_pids(a.pid)) > 0
ORDER BY a.query_start; Cancel work before terminating a session
pg_cancel_backend requests cancellation of the current query while preserving the connection; pg_terminate_backend ends the session and rolls back its transaction. The caller must own the target role, be a member of it, or hold pg_signal_backend, while only superusers may signal superuser backends. Verify PID, user, database, query, and age immediately before acting because PIDs are reusable.
SELECT pid, usename, datname, state, query_start, query
FROM pg_stat_activity
WHERE pid = 12345;
-- After human verification: SELECT pg_cancel_backend(12345); Note: Do not automate termination from stale PID lists; cancel first unless an incident runbook requires stronger action.
Capture evidence and retry only safe transaction units
log_lock_waits records waits that exceed deadlock_timeout and log_min_error_statement can preserve failed SQL, subject to sensitive-data policies. SQLSTATE 40P01 identifies deadlock_detected and 40001 identifies serialization_failure; retry with bounded exponential jitter only when the whole transaction is safe to repeat. Timeouts and user cancellation use different error states and may represent overload, not transient serialization.
SELECT name, setting, unit, source
FROM pg_settings
WHERE name IN ('log_lock_waits', 'deadlock_timeout', 'log_min_error_statement')
ORDER BY name; Note: Change logging through approved configuration management; query text can contain sensitive values.
Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
- PostgreSQL Global Development GroupExplicit Lockingpostgresql.org
- PostgreSQL Global Development GroupClient Connection Defaultspostgresql.org
- PostgreSQL Global Development GroupLock Managementpostgresql.org
- PostgreSQL Global Development GroupMonitoring Database Activitypostgresql.org
- PostgreSQL Global Development Grouppg_lockspostgresql.org
- PostgreSQL Global Development GroupSystem Information Functionspostgresql.org
- PostgreSQL Global Development GroupSystem Administration Functionspostgresql.org
- PostgreSQL Global Development GroupPostgreSQL Error Codespostgresql.org
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



