#ruby #postgresql #database-locking
#ruby #postgresql #блокировка базы данных
Вопрос:
Я использую драгоценный камень pg_lock для управления консультативными блокировками Postgres для координации между процессами, чтобы избежать условий гонки. У меня есть блокировка, которая выходит из строя с ошибкой about Was unable to aquire a lock "my_lock_name" after N attempts
, которая говорит мне, что что-то еще уже удерживает блокировку. Как я могу найти эту блокировку в базовой базе данных, чтобы узнать больше информации о том, что ее удерживает?
Ответ №1:
Вот как перейти от PgLock#lock!
вызова к фактической блокировке в базе данных, чтобы получить больше информации о том, что ее удерживает:
- Найдите ключи блокировки, которые PgLock использует для вашего имени блокировки. Это происходит в двух половинах (
amp; 0xFFFF_FFFF
это необходимо, потому что PgLock работает с этими числами как целые числа со знаком, но Postgres обрабатывает их как неподписанные):- Первый из
2147483648
них. Это простоPG_LOCK_SPACE amp; 0xFFFF_FFFF
из pg_lock.rb . - Вторую блокировку можно получить, заменив ваше имя блокировки в следующем:
PgLock.new(name: '').send(:key, "my_lock_name") amp; 0xFFFF_FFFF
- Первый из
- Запустите этот запрос в Postgres, чтобы найти ваш ключ в
pg_locks
таблице,objid
заменив его на ключ из ключа, который вы получили выше: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
Это покажет информацию о любых активных блокировках, удерживаемых на этом ключе. В частности, столбец pid — это pid сервера posgres для соединения, содержащего блокировку.
- Вы можете получить дополнительную информацию о том, что делает соединение, удерживающее блокировку, из
pg_stat_activity
:SELECT * FROM pg_stat_activity WHERE pid = PID;
- В крайнем случае вы можете разорвать соединение и принудительно снять блокировку с помощью:
SELECT pg_terminate_backend(PID);