PostgreSQL Lock Contention
The slow query may be waiting on work that is already finished.
The slow query may be waiting on work that is already finished.
Identify blockers and waiters rather than optimizing the waiting statement in isolation.
Long transactions can turn ordinary DDL/DML into queues that amplify latency.
A fast DDL statement can still be dangerous if it waits for or queues behind long-running transactions.
Capture lock state and transaction age during the event when possible; screenshots after the fact often miss the chain.
ALTER TABLE still needs an exclusive lock. While it waits, every new query on the table waits behind it. See the lock-queue lab: 14 seconds of zero reads.log_lock_waits is on.pg_locks will show the row.” A session waiting on a row lock usually shows as waiting on the other transaction’s transactionid, not on a row. pg_blocking_pids() resolves that for you.Read-only. Run them during the problem window if you can; most of these views show current state, not history.
-- Blocking chain: who waits on whom
SELECT pid,
pg_blocking_pids(pid) AS blocked_by,
state,
wait_event_type || ':' || wait_event AS wait,
now() - xact_start AS xact_age,
left(query, 60) AS query
FROM pg_stat_activity
WHERE cardinality(pg_blocking_pids(pid)) > 0
OR pid IN (SELECT unnest(pg_blocking_pids(pid)) FROM pg_stat_activity)
ORDER BY xact_start;
-- Long-running and idle transactions
SELECT pid, usename, application_name, state,
now() - xact_start AS xact_age,
left(query, 60) AS last_query
FROM pg_stat_activity
WHERE xact_start < now() - interval '1 minute'
ORDER BY xact_start;lock_timeout, and adding one needs retry logic in the deploy tool.For the wider diagnostic sequence, read the PostgreSQL locking and concurrency guide.
Start with the problem and the evidence you already have. You will get a direct answer on whether a scoped investigation is the right next step.
Prefer to talk first? Book a 20-minute triage call.