I'm using the pg_lock gem to manage Postgres advisory locks for coordinating between processes to avoid race conditions. I have a lock that is failing with an error about Was unable to aquire a lock "my_lock_name" after N attempts
, which tells me that something else is already holding onto the lock. How can I look up this lock in the underlying database to find out more information about what's holding it?
Here’s how to go from a PgLock#lock!
call to the actual lock in the database to get more info about what’s holding it:
& 0xFFFF_FFFF
is necessary because PgLock works with these numbers as signed ints, but Postgres treats them as unsigned):
2147483648
. This is simply PG_LOCK_SPACE & 0xFFFF_FFFF
from pg_lock.rb.PgLock.new(name: '').send(:key, "my_lock_name") & 0xFFFF_FFFF
pg_locks
table, replacing the objid
with the one from the key you got above:
SELECT *
FROM pg_locks
WHERE locktype = 'advisory' AND
classid = 2147483648 AND -- First key, the static PG_LOCK_SPACE one
objid = 2928511612 AND -- Second key, based on your lock name
objsubid = 2; -- key is int pair, not single bigint
This will show information about any active locks being held on this key. In particular the pid column is the posgres server pid of the connection holding the lock.pg_stat_activity
:
SELECT * FROM pg_stat_activity WHERE pid = PID;
SELECT pg_terminate_backend(PID);