Это нормальное поведение; проблема в вашей рабочей нагрузке.
Вы правы, что ALTER TABLE ... ADD COLUMN
- это очень быстрая операция. Это не проблема. Проблема в том, что для такого ALTER TABLE
нужна короткая блокировка ACCESS EXCLUSIVE
на таблице, поскольку она изменяет структуру таблицы.
Такая блокировка ACCESS EXCLUSIVE
не совместима с блокировкой ACCESS SHARE
, что SELECT
оператор ставит на стол. Вот почему: как должен вести себя оператор SELECT
, если таблица изменяется во время ее работы?
Теперь проблема в том, что либо ваши запросы занимают много времени, либо кто-то забыл закрыть транзакцию, которая имеет блокировка на столе.
Вы можете проверить это с помощью
SELECT pid, a.state, a.xact_start
FROM pg_locks AS l
JOIN pg_stat_activity AS a USING (pid)
WHERE l.relation = 'Users'::regclass;
, который покажет все транзакции, которые имеют блокировку на столе и когда они начались.
Сейчас ваш ALTER TABLE
должен ждать, пока все эти транзакции не будут выполнены, и все короткие операторы SELECT
, которые будут выданы позже, должны стоять в очереди за ALTER TABLE
.
, как только ALTER TABLE
получит заблокировать это нужно, это будет сделано очень быстро и снять блокировку на столе. Теперь все остальные операторы, находящиеся в очереди, будут одновременно освобождены и создадут высокую нагрузку на ваш компьютер.
Решение состоит из двух частей:
Исправьте приложение так, чтобы оно сразу закрывало транзакции.
Максимально уменьшите max_connections
, используя пул соединений. Тогда количество операторов, которые можно заблокировать, будет ограничено, и опасность перегрузки машины станет меньше.