Наскільки я розумію, той факт, що наш запит чекає на замок, означає, що він завжди чекав на замок, і він ніколи нічого не змінював.
Праворуч - якщо ви бачите, що pg_stat_activity.waiting є "істинним" для ALTER TABLE, це майже напевно означає, що він терпляче чекає блокування ACCESS EXCLUSIVE на його цільовій таблиці та його реальної роботи (переписування таблиці, якщо потрібно, зміна каталогів) , відновлення індексів тощо) ще не почалося.
Чи безпечно для нас прямо скасувати запит ALTER TABLE? Або можливо, що запит вже щось змінив, і скасування його залишило б нашу базу даних в напівдорожному стані якогось типу?
Скасування запитів (або, що еквівалентно, повернення транзакції) в PostgreSQL не має жодних небезпек пошкодження бази даних, які, можливо, були опудані в деяких інших базах даних (наприклад, жахливе попередження внизу цієї сторінки). Ось чому в останніх версіях користувачі, які не користуються суперпоширенням, вільні у використанні pg_cancel_backend()
та pg_terminate_backend()
знищенні власних запитів, що виконуються в інших пакетах - вони безпечні для використання, не замислюючись про пошкодження бази даних. Зрештою, PostgreSQL має бути готовим до вирішення будь-яких процесів, що вбиваються, наприклад, SIGKILL від кілера OOM, відключення сервера тощо. Для цього потрібен журнал 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 і (якщо вона успішна) COMMIT обмотана навколо неї. Групу висловлювань, оточених BEGIN та COMMIT, іноді називають блоком транзакцій.
Тож скасування того ALTER TABLE
, що через pg_cancel_backend()
або Ctrl-C, видане з керуючого запису psql, матиме аналогічний ефект, як якщо б ви це зробили
BEGIN;
ALTER TABLE ... ;
ROLLBACK;
(хоча, як ви сподіваємось побачити, скасування такого дорогого ALTER TABLE
може врятувати базу даних від безлічі шліфування, якщо ви все ROLLBACK
одно збираєтесь .)