Postgresql - Почему команда DROP VIEW висит?
Я хочу выполнить простой DROP VIEW ...
, но он зависает.
Я выполнил этот запрос SELECT * FROM pg_locks WHERE NOT granted
, взятый с этой страницы Контроль блокировки.
Однако следующий запрос, который они предлагают, не возвращает результатов:
SELECT bl.pid AS blocked_pid,
a.usename AS blocked_user,
kl.pid AS blocking_pid,
ka.usename AS blocking_user,
a.query AS blocked_statement
FROM pg_catalog.pg_locks bl
JOIN pg_catalog.pg_stat_activity a ON a.pid = bl.pid
JOIN pg_catalog.pg_locks kl ON kl.transactionid = bl.transactionid AND kl.pid != bl.pid
JOIN pg_catalog.pg_stat_activity ka ON ka.pid = kl.pid
WHERE NOT bl.granted;
Где я должен смотреть сейчас?
Ответы
Ответ 1
Наконец я выясняю, что было не так. Вот шаги, чтобы найти основную причину:
Решение
Шаг 1: список запрошенных блокировок не предоставлен
select * from pg_locks where not granted;
В моем случае попытка заблокировать в режиме AccessExclusiveLock
представление, которое я хочу отбросить, не было предоставлено. Вот почему мой DROP VIEW...
зависает.
Шаг 2: Найдите, какой другой процесс удерживал конфликтующую блокировку
select * from pg_locks where relation = <oid_of_view>
Здесь я перечисляю все процессы, блокирующие или пытающиеся заблокировать мой взгляд. Я обнаружил два процесса: один, который хочет отбросить представление, и... другой.
Шаг 3: Узнайте, что другие процессы сейчас делают
select xact_start,query_start,backend_start,state_change,state from pg_stat_activity where pid in (<list_of_other_process(es)_pid>);
У меня был только один процесс, удерживающий блокировку в моем случае. Удивительно, но его состояние было: в режиме ожидания
Мне не удалось отбросить представление, потому что другой процесс не работал в транзакции. Я просто убиваю это, чтобы решить мою проблему. Например, если procpid
был 8484, и пусть предположим, что мой сервер postgresql работает под управлением Linux, то в оболочке я выполняю следующую команду:
$ kill -9 8484
обсуждение
Если вы столкнулись с подобной проблемой, вы можете быстро узнать, что происходит, повторив шаги 1,2,3. Вам может потребоваться настроить Шаг 2, чтобы найти другие конфликтующие процессы.
Рекомендации
Ответ 2
У меня была похожая проблема, но принятый ответ не работал для меня, так как у меня нет доступа администратора, чтобы убить какой-либо процесс. Вместо этого, вот как мне удалось решить проблему:
- Выпуск
SELECT * FROM pg_stat_activity;
к статистике о деятельности PostgreSQL. - В столбце
query
найдите запросы, которые читаются из этого представления. Вы можете сузить область поиска, просматривая только строки, связанные с вашим именем пользователя (столбец имени username
) или query_start
если вы знаете, когда возникла проблема. Может быть несколько строк, связанных с вашим нежелательным представлением. - Определите все
pid
из строк на SELECT pg_terminate_backend(<pid>);
шаге и вставьте их в SELECT pg_terminate_backend(<pid>);
(вместо <pid>
) один за другим и выдайте их.
Теперь вы должны иметь возможность отказаться от своего взгляда.
Обратите внимание, что когда вы завершаете бэкэнд-процессы с помощью pg_terminate_backend()
, вы можете столкнуться с некоторыми ошибками. Причина в том, что завершение какого-либо процесса может автоматически завершить другие процессы. Следовательно, некоторые из идентифицированных PID могут быть недействительными к тому времени.