Насколько я понимаю, тот факт, что наш запрос ожидает блокировки, означает, что он всегда ожидал блокировки и никогда ничего не менял.
Правильно - если вы видите, что pg_stat_activity.waiting "true" для ALTER TABLE, это почти наверняка означает, что он терпеливо ожидает блокировки ACCESS EXCLUSIVE на своей целевой таблице и ее реальной работы (переписывает таблицу при необходимости, изменяет каталоги , восстановление индексов и т. д.) еще не началось.
Безопасно ли нам полностью отменить наш запрос ALTER TABLE? Или возможно, что запрос уже изменил что-то, и его отмена оставила бы нашу базу данных в каком-то наполовину состоянии?
Отмена запросов (или, что то же самое, откат транзакции) в PostgreSQL не имеет каких-либо рисков повреждения базы данных, которые вы могли бы напугать в некоторых других базах данных (например, ужасающее предупреждение внизу этой страницы). Вот почему пользователи, не являющиеся суперпользователями, в последних версиях могут свободно использовать pg_cancel_backend()
и pg_terminate_backend()
уничтожать свои собственные запросы, выполняемые в других бэкэндах - их можно безопасно использовать, не беспокоясь о повреждении базы данных. В конце концов, PostgreSQL должен быть подготовлен к тому, чтобы справляться с любыми процессами, такими как SIGKILL от OOM killer, выключение сервера и т. Д. Вот для чего нужен журнал WAL .
Возможно, вы также видели, что в PostgreSQL можно выполнять большинство команд DDL, вложенных в транзакцию (с несколькими операторами), например
BEGIN;
ALTER TABLE foo ...;
ALTER TABLE bar ...;
-- more stuff
COMMIT; -- or ROLLBACK; if you've changed your mind
(Потрясающе, если убедиться, что миграция схемы происходит либо вообще, либо вообще не происходит.) Однако вы сказали:
Мы не завернули ALTER TABLE
в транзакции.
Это хорошо для одной команды - из документов ,
PostgreSQL фактически обрабатывает каждый оператор SQL как выполняемый в транзакции. Если вы не выполняете команду BEGIN, то каждый отдельный оператор имеет неявный BEGIN и (в случае успеха) обертку вокруг него. Группу операторов, окруженную BEGIN и COMMIT, иногда называют блоком транзакции.
Поэтому отмена, что ALTER TABLE
либо через pg_cancel_backend()
Ctrl-C , либо из контрольной подсказки psql, будет иметь такой же эффект, как если бы вы сделали
BEGIN;
ALTER TABLE ... ;
ROLLBACK;
(хотя, как вы надеетесь, отмена этой дорогой процедуры ALTER TABLE
может спасти базу данных от большого количества ненужных операций измельчения, если вы все равно собираетесь ROLLBACK
.)