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

У меня была похожая проблема, но принятый ответ не работал для меня, так как у меня нет доступа администратора, чтобы убить какой-либо процесс. Вместо этого, вот как мне удалось решить проблему:

  1. Выпуск SELECT * FROM pg_stat_activity; к статистике о деятельности PostgreSQL.
  2. В столбце query найдите запросы, которые читаются из этого представления. Вы можете сузить область поиска, просматривая только строки, связанные с вашим именем пользователя (столбец имени username) или query_start если вы знаете, когда возникла проблема. Может быть несколько строк, связанных с вашим нежелательным представлением.
  3. Определите все pid из строк на SELECT pg_terminate_backend(<pid>); шаге и вставьте их в SELECT pg_terminate_backend(<pid>); (вместо <pid>) один за другим и выдайте их.

Теперь вы должны иметь возможность отказаться от своего взгляда.

Обратите внимание, что когда вы завершаете бэкэнд-процессы с помощью pg_terminate_backend(), вы можете столкнуться с некоторыми ошибками. Причина в том, что завершение какого-либо процесса может автоматически завершить другие процессы. Следовательно, некоторые из идентифицированных PID могут быть недействительными к тому времени.