Как снять возможные блокировки строк Postgres?

Я запустил оператор обновления для большой таблицы PostgreSQL через интерфейс phpPgAdmin. Время истекло, так как оно длилось слишком долго.

Теперь я могу обновить некоторые строки из этой таблицы, но не все. Попытка обновить некоторые строки будет зависать.

Строки заблокированы? Как я могу разрешить обновление этих строк?

Ответы на вопрос(5)

Вот вид, который делает это немного проще, чем прямое использование pg_locks:

CREATE OR REPLACE VIEW public.active_locks AS 
 SELECT t.schemaname,
    t.relname,
    l.locktype,
    l.page,
    l.virtualtransaction,
    l.pid,
    l.mode,
    l.granted
   FROM pg_locks l
   JOIN pg_stat_all_tables t ON l.relation = t.relid
  WHERE t.schemaname <> 'pg_toast'::name AND t.schemaname <> 'pg_catalog'::name
  ORDER BY t.schemaname, t.relname;

Затем вы просто выбираете из вида:

SELECT * FROM active_locks;

И убить его с помощью:

SELECT pg_cancel_backend('%pid%');

Другие решения:http: //wiki.postgresql.org/wiki/Lock_Monitorin

 Gilbou20 янв. 2017 г., 13:40
для уничтожения типа "SELECT pg_cancel_backend (pid) FROM active_locks;" вмест
 Deepak Kumar25 янв. 2017 г., 12:30
use "SELECT pg_terminate_backend ('pid')", чтобы убить насильно
 a_horse_with_no_name14 апр. 2014 г., 15:09
Нет представления или таблицы с именемactive_locks в Postgres. Ты имеешь в видуpg_locks?
 Chris15 апр. 2014 г., 11:27
Вы правы, в нашей базе данных было пользовательское представление, я отредактировал ответ.
 Thomas Kekeisen18 апр. 2014 г., 12:24
В моем случае твойpg_cancel_backend в сочетании с qeury здесь: Stackoverflow.com / а / 10317371/301277 позволил мне удалить все "забытые" блокировки. Благодарность
Решение Вопроса

ли более позднюю версию (это может относиться и к более ранним версиям, я не знаю).

Я предполагаю, что вы имеете в виду, что тайм-аут phpPgAdmin истек - бэкэнд PostgreSQL займет столько времени, сколько потребуется для выполнения запроса / обновления. В этом случае возможно, что исходный сеанс еще жив, а запрос UPDATE все еще выполняется. Я предлагаю выполнить следующий запрос (взят из глава 24 документации PostgreSQL) на компьютере, на котором размещен серверный процесс PostgreSQL, чтобы проверить, жив ли сеанс:

ps auxwww|grep ^postgres

олжно появиться несколько строк: 1 дляpostmaster главный процесс, и 1 для процессов «писатель», «буфер статистики» и «сборщик статистики». Все остальные строки предназначены для процессов, обслуживающих соединения с БД. Эти строки будут содержать имя пользователя и имя базы данных.

Надеюсь, из этого видно, что сеанс, в котором вы выполняли оригинальное ОБНОВЛЕНИЕ, все еще висит. Хотя в теории вы можете найти более подробную информацию поSELECT в системном представленииpg_stat_activity, по умолчанию PostgreSQL не настроен для заполнения наиболее полезных полей (таких какcurrent_query а такжеquery_start). См. Главу 24, чтобы узнать, как это сделать в будущем.

Если ты видишь, что сеанс все еще там, убей его. Вы должны войти в систему как пользователь, выполняющий процесс (обычноpostgres) или root, чтобы сделать это - если вы не запускаете сервер самостоятельно, попросите своего администратора базы данных сделать это за вас.

Еще одна вещь: для обновления строк в таблице PostgreSQL избегает использования блокировок. Вместо этого он позволяет каждой записывающей транзакции создавать новую «версию» БД, которая становится «текущей версией», когда транзакция фиксируется, при условии, что она не конфликтует с обновлениями, сделанными тем временем другими транзакциями. Поэтому я подозреваю, что «зависание», которое вы видите, вызвано чем-то другим, хотя я не уверен. (Вы проверили очевидные вещи, например, заполнен ли раздел диска, содержащий БД?)

 Liam30 июн. 2009 г., 13:57
Отлично, это сработало, спасибо. Обратите внимание, что когда я уничтожил процесс, который вызывал проблему, это позволило запустить некоторые другие процессы, которые ожидали снятия блокировки. Это вызвало некоторые дополнительные проблемы. Я должен был убить процессы, помеченные как «WAITING», когда я запускал ps auxwww | grep ^ postgres, прежде чем убивать первый проблемный процесс.
 j_random_hacker30 июн. 2009 г., 14:01
Рад, что смог помочь :
 Noumenon31 июл. 2017 г., 18:19
"Если ты видишь, что сеанс все еще там, убей его." - Для новичков, посмотрите, где написаноpostgres 15398 ... idle in transaction или что-то еще и наберитеkill 15398 в замазке.

но если он похож на другие, я бы сказал, что нужно прервать соединение / завершить транзакцию, которая удерживает блокировки.

я обычно следую им по порядку.

Найдите долгосрочные запросы в вашей БД, выполнив следующий запрос. Это поможет вам получить PID для продолжительного запроса, который блокирует ваше обновление.

SELECT
pid,
now() - pg_stat_activity.query_start AS duration,
query,
state
FROM pg_stat_activity
WHERE (now() - pg_stat_activity.query_start) > interval '5 minutes';

или, если вы можете узнать, какие процессы удерживают блокировку для определенной таблицы, выполнив этот запрос

SELECT *
FROM pg_locks l
JOIN pg_class t ON l.relation = t.oid AND t.relkind = 'r'
WHERE t.relname = 'Bill';

Как только вы выясните PID, который является «активным» и заблокирующим ваше обновление, вы можете убить его, выполнив этот запрос. Требуется некоторое время, чтобы убить процесс.

SELECT pg_cancel_backend(__pid__);

Проверьте, запустив Query 2, если процесс завершен. Если он все еще активен, убейте этот процесс, выполнив этот запрос.

SELECT pg_terminate_backend(__pid__);

Просто

Получите активные блокировки от pg_locks:

select t.relname, l.locktype, page, virtualtransaction, pid, mode, предоставляемый из pg_locks l, pg_stat_all_tables t, где l.relation = t.relid, порядок по отношению asc;

Скопируйте pid (например: 14210) из приведенного выше результата и подставьте в приведенную ниже команду.

SELECT pg_terminate_backend ('14210')

 Kulasangar17 янв. 2019 г., 23:50
это сработало как шарм.

Ваш ответ на вопрос