Czy długotrwałe zapytanie Postgres zostanie przerwane, jeśli połączenie zostanie utracone / zerwane?

20

Jeśli otworzę połączenie z Postgres i wydam długo działające zapytanie, a następnie przerwie połączenie (np. Zabije proces klienta, który otworzył połączenie), czy długo działające zapytanie będzie kontynuowane, czy też zostanie automatycznie przerwane? Czy to można skonfigurować?

(Używam Postgresql 9.2.9)

Rob Bednark
źródło

Odpowiedzi:

32

"To zależy".

Jeśli klient zniknie z powodu utraty połączenia sieciowego, zapytanie zwykle będzie działać, dopóki nie zostanie pobrane wystarczająca liczba wierszy do wypełnienia bufora wysyłania do sieci, a następnie zatrzymaj się i utknij, aż połączenie TCP spadnie, w którym to momencie zostanie przerwane. Jeśli zakończy się przed zapełnieniem bufora wysyłania TCP, zakończy się pomyślnie, więc jeśli jest to automatyczne zatwierdzanie, zapytanie zostanie zatwierdzone.

Jeśli klient zostanie zabity w sposób, który system operacyjny klienta może zgłosić serwerowi za pośrednictwem protokołu TCP RST (np. Segfault / crash klienta, SIGTERM, SIGKILL itp.), Serwer PostgreSQL ustawi flagę przerwania. Następnym razem, gdy zapytanie sprawdzi przerwania podczas wykonywania, zobaczy flagę i przerwie działanie. Czasami zapytanie może powodować duże obciążenie procesora w kodzie, który nie sprawdza przerwań - niektórych rozszerzeń i kilku miejsc w rdzeniu PostgreSQL - w takim przypadku może nie zauważyć przerwania przez długi czas i kontynuować działanie. Jednak prawie zawsze zobaczy przerwanie i przerwanie przed zakończeniem i zatwierdzeniem, jeśli jest to automatyczne zatwierdzanie.

Jeśli klient zostanie zabity przez coś takiego jak nagłe ponowne uruchomienie systemu operacyjnego, aby host klienta nagle nic nie wiedział o połączeniu TCP, ale nadal mógł odpowiadać w sieci, zapytanie prawdopodobnie zostanie przerwane przy pierwszej próbie napisania wiersza, na przykład Jeff powiedział, ponieważ host klienta wyśle ​​protokół TCP RST w odpowiedzi na pierwszy pakiet wysłany przez serwer po ponownym uruchomieniu. PostgreSQL sprawdza przerwania w każdym wysyłanym wierszu.

Tego zachowania nie można skonfigurować. Jeśli chodzi o PostgreSQL, jeśli klient zniknie, jego zadaniem jest zakończenie wszelkich zapytań, które klient uruchomił. Aby to zmienić, potrzebujesz jakiegoś tokena zakończenia zapytania, który można uzyskać na początku zapytania, a następnie użyj, aby zapytać serwer o zapytanie za pośrednictwem innego połączenia później. Zasadniczo będziesz musiał zaimplementować zapytania asynchroniczne / w tle. Prawdopodobnie fajna funkcja, ale obecnie nie obsługiwana.

Jeśli zapytanie jest zatwierdzane automatycznie lub jeśli zapytanie było COMMITw locie w momencie, gdy zabiłeś klienta / utraciłeś połączenie, możliwe, że transakcja jest w nieokreślonym stanie, w którym klient nie wie, czy lub nie popełnił. Nie ma prawdziwego sposobu, aby się dowiedzieć, poza szukaniem wpływu transakcji na dane.

Tam, gdzie jest to niedopuszczalne, można użyć zatwierdzania dwufazowego i menedżera transakcji po stronie klienta.

Craig Ringer
źródło
1
Wow, dokładnie to, czego szukałem, doskonała szczegółowa odpowiedź! Dzięki @Craig_Ringer!
Rob Bednark,
2

Będzie działał, dopóki nie spróbuje zwrócić wierszy do połączenia i nie wykryje pęknięcia. W przypadku zapytania, które wykonuje całą pracę przed zwróceniem wierszy, zostanie ono zasadniczo wykonane do końca.

jjanes
źródło
Dzięki @jjanes. Czy możesz wskazać dokumentację lub kod źródłowy, który to wskazuje?
Rob Bednark