postgres locks release - ghdrako/doc_snipets GitHub Wiki
- https://stackoverflow.com/questions/10317114/postgresql-drop-table-doesnt-work
- https://eric.nz/posts/postgres-table-lock/
- https://www.citusdata.com/blog/2018/02/15/when-postgresql-blocks/
- https://www.crunchydata.com/blog/one-pid-to-lock-them-all-finding-the-source-of-the-lock-in-postgres
-- gets you the PID
SELECT pid, relname FROM pg_locks l JOIN pg_class t ON l.relation = t.oid AND t.relkind = 'r' WHERE t.relname = 'YOUR_TABLE_NAME'
-- cancel the running query
SELECT pg_cancel_backend(PID);
-- if cancel not work end the process and its associated database connection
SELECT pg_terminate_backend(YOUR_PID_FROM_PREVIOUS_QUERY);
If PID is null:
- Check if PostgreSQL has a pending prepared transaction that's never been committed or rolled back:
SELECT database, gid FROM pg_prepared_xacts;
- If you get a result, then for each transaction gid you must execute a ROLLBACK from the database having the problem:
ROLLBACK PREPARED 'the_gid';
For further information, click here.
Could not drop table. Could not reboot the database so tested a few things until this sequence worked :
- truncate table foo;
- drop index concurrently foo_something; times 4-5x
- alter table foo drop column whatever_foreign_key; times 3x
- alter table foo drop column id;
- drop table foo;
proactive locks manage
Logging lock_waits
You can log any time your query is waiting on a lock by turning on log_lock_waits. Lock_waits in your logs can be a good indicator that processes are being contentious. There is virtually no overhead on enabling this and itโs very safe for production databases. This is set to โonโ by default on Crunchy Bridge clusters:
log_lock_waits = on
Set a lock timeout
We generally recommend clients set a lock_timeout within a session so that it will cancel the transaction and relinquish any locks it was holding after a certain period of time. This helps to prevent other processes from getting caught up behind them in a chain.
ALTER SYSTEM SET lock_timeout = '10s';
Find the source of the lock
WITH sos AS (
SELECT array_cat(array_agg(pid),
array_agg((pg_blocking_pids(pid))[array_length(pg_blocking_pids(pid),1)])) pids
FROM pg_locks
WHERE NOT granted
)
SELECT a.pid, a.usename, a.datname, a.state,
a.wait_event_type || ': ' || a.wait_event AS wait_event,
current_timestamp-a.state_change time_in_state,
current_timestamp-a.xact_start time_in_xact,
l.relation::regclass relname,
l.locktype, l.mode, l.page, l.tuple,
pg_blocking_pids(l.pid) blocking_pids,
(pg_blocking_pids(l.pid))[array_length(pg_blocking_pids(l.pid),1)] last_session,
coalesce((pg_blocking_pids(l.pid))[1]||'.'||coalesce(case when locktype='transactionid' then 1 else array_length(pg_blocking_pids(l.pid),1)+1 end,0),a.pid||'.0') lock_depth,
a.query
FROM pg_stat_activity a
JOIN sos s on (a.pid = any(s.pids))
LEFT OUTER JOIN pg_locks l on (a.pid = l.pid and not l.granted)
ORDER BY lock_depth;