Soweit ich weiß, bedeutet die Tatsache, dass unsere Abfrage auf eine Sperre wartet, dass sie immer auf eine Sperre gewartet hat und nie etwas geändert hat.
Richtig - wenn Sie sehen, dass pg_stat_activity.waiting für eine ALTER TABLE "true" ist, bedeutet dies mit ziemlicher Sicherheit, dass sie geduldig auf die ACCESS EXCLUSIVE-Sperre für ihre Zieltabelle und ihre eigentliche Arbeit wartet (ggf. Umschreiben der Tabelle, Ändern von Katalogen) , Neuerstellung von Indizes usw.) hat noch nicht begonnen.
Ist es für uns sicher, unsere ALTER TABLE-Abfrage sofort abzubrechen? Oder ist es möglich, dass die Abfrage bereits etwas geändert hat und ein Abbrechen unsere Datenbank in einem halben Zustand belassen würde?
Das Abbrechen von Abfragen (oder gleichwertig das Zurücksetzen einer Transaktion) in PostgreSQL birgt keine Gefahr für die Beschädigung von Datenbanken, durch die Sie in bestimmten anderen Datenbanken möglicherweise erschreckt wurden (z. B. die schreckliche Warnung am Ende dieser Seite). Deshalb Nicht-Superuser sind, in den letzten Versionen, frei zu verwenden pg_cancel_backend()
und pg_terminate_backend()
eigene Abfragen zu töten in anderen Backends laufen - sie sind sicher ohne Sorgen um eine Beschädigung der Datenbank zu verwenden. Schließlich muss PostgreSQL auf jeden Prozess vorbereitet sein, der abgebrochen wird, z. B. SIGKILL vom OOM-Killer, Herunterfahren des Servers usw. Dafür ist das WAL-Protokoll gedacht .
Möglicherweise haben Sie auch gesehen, dass in PostgreSQL die meisten DDL-Befehle ausgeführt werden können, die in einer Transaktion (mit mehreren Anweisungen) verschachtelt sind, z
BEGIN;
ALTER TABLE foo ...;
ALTER TABLE bar ...;
-- more stuff
COMMIT; -- or ROLLBACK; if you've changed your mind
(Hervorragend geeignet, um sicherzustellen, dass Schema-Migrationen entweder alle zusammen oder gar nicht durchgeführt werden.) Sie sagten jedoch:
Wir haben nicht wickeln die ALTER TABLE
in einer Transaktion.
Das ist in Ordnung für einen einzelnen Befehl - aus den Dokumenten ,
PostgreSQL behandelt tatsächlich jede SQL-Anweisung als innerhalb einer Transaktion ausgeführt. Wenn Sie keinen BEGIN-Befehl ausgeben, wird jede einzelne Anweisung mit einem impliziten BEGIN und (falls erfolgreich) COMMIT umwickelt. Eine Gruppe von Anweisungen, die von BEGIN und COMMIT umgeben sind, wird manchmal als Transaktionsblock bezeichnet.
Wenn Sie dies ALTER TABLE
entweder über pg_cancel_backend()
oder über eine Strg-C-Taste, die über die steuernde psql-Eingabeaufforderung ausgegeben wird, abbrechen, hat dies einen ähnlichen Effekt wie bei Ihnen
BEGIN;
ALTER TABLE ... ;
ROLLBACK;
(Wie Sie hoffentlich sehen werden, kann das Abbrechen dieser Kosten ALTER TABLE
die Datenbank vor unnötigem Schleifen bewahren, wenn Sie es ROLLBACK
trotzdem tun .)