Wird eine Postgres-Langzeitabfrage abgebrochen, wenn die Verbindung unterbrochen wird?


20

Wenn ich eine Verbindung zu Postgres öffne und eine Langzeitabfrage ausstelle und dann die Verbindung unterbreche (z. B. den Client-Prozess beenden, der die Verbindung geöffnet hat), wird die Langzeitabfrage dann weiter ausgeführt oder wird sie automatisch abgebrochen? Ist das konfigurierbar?

(Ich benutze Postgresql 9.2.9)

Antworten:


32

"Es hängt davon ab, ob".

Wenn der Client aufgrund eines Netzwerkverbindungsverlusts verschwindet, wird die Abfrage im Allgemeinen ausgeführt, bis genügend Zeilen abgerufen wurden, um den Netzwerksendepuffer zu füllen. Halten Sie dann an und bleiben Sie hängen, bis die TCP-Verbindung getrennt wird. An diesem Punkt wird sie abgebrochen. Wenn es abgeschlossen ist, bevor es den TCP-Sendepuffer füllt, wird es erfolgreich abgeschlossen. Wenn es sich also um eine automatische Festschreibung handelt, wird die Abfrage festgeschrieben.

Wenn der Client auf eine Weise beendet wird, dass das Betriebssystem des Clients dem Server über eine TCP-RST-Verbindung Bericht erstatten kann (z. B. Client-Fehler / Absturz, SIGTERM, SIGKILL usw.), setzt der PostgreSQL-Server das Interrupt-Flag. Wenn die Abfrage das nächste Mal nach Interrupts sucht, wird das Flag angezeigt und der Vorgang abgebrochen. Manchmal führt eine Abfrage eine CPU-schwere Arbeit innerhalb des Codes aus, die nicht auf Interrupts überprüft - einige Erweiterungen und einige Stellen innerhalb des PostgreSQL-Kerns -. In diesem Fall bemerkt sie den Interrupt möglicherweise lange nicht und läuft weiter. Es wird jedoch so gut wie immer die Unterbrechung und den Abbruch sehen, bevor es abgeschlossen und festgeschrieben wird, ob es sich um eine automatische Festschreibung handelt.

Wenn der Client durch so etwas wie einen plötzlichen Neustart des Betriebssystems getötet wird, sodass der Client- Host plötzlich nichts über die TCP-Verbindung weiß, aber dennoch im Netzwerk antworten kann, wird die Abfrage wahrscheinlich abgebrochen, wenn er zum ersten Mal versucht, eine Zeile zu schreiben, z Jeff sagte, weil der Host des Clients eine TCP-RST als Antwort auf das erste vom Server nach dem Neustart gesendete Paket sendet. PostgreSQL überprüft jede gesendete Zeile auf Interrupts.

Dieses Verhalten ist nicht konfigurierbar. Für PostgreSQL besteht die Aufgabe des Clients darin, alle vom Client ausgeführten Abfragen zu beenden, wenn er abbricht. Um dies zu ändern, benötigen Sie ein Query-Completion-Token, das Sie beim Query-Start erhalten können, und fragen Sie den Server später über eine andere Verbindung nach der Query. Im Wesentlichen müssten Sie asynchrone / Hintergrundabfragen implementieren. Möglicherweise ein nettes Feature, wird aber momentan nicht unterstützt.

Wenn es sich bei der Abfrage um eine automatische Festschreibung handelt oder wenn Ihre Abfrage COMMITzu dem Zeitpunkt ausgeführt wurde, als Sie den Client beendet / die Verbindung unterbrochen haben, befindet sich eine Transaktion möglicherweise in einem unbestimmten Zustand, in dem der Client nicht weiß, ob oder nicht verpflichtet. Es gibt keine echte Möglichkeit, dies herauszufinden, außer nach den Auswirkungen der Transaktion auf die Daten zu suchen.

Wenn dies nicht akzeptabel ist, können Sie ein zweiphasiges Festschreiben und einen clientseitigen Transaktionsmanager verwenden.


1
Wow, genau das, wonach ich gesucht habe, eine ausgezeichnete, detaillierte Antwort! Vielen Dank @Craig_Ringer!
Rob Bednark


2

Es wird so lange ausgeführt, bis versucht wird, Zeilen an die Verbindung zurückzugeben, und der Bruch erkannt wird. Bei einer Abfrage, die die gesamte Arbeit erledigt, bevor Zeilen zurückgegeben werden, wird sie im Wesentlichen vollständig ausgeführt.


Vielen Dank, @jjanes. Können Sie auf eine Dokumentation oder einen Quellcode verweisen, die dies anzeigen?
Rob Bednark
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.