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)

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.


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.


Dzięki @jjanes. Czy możesz wskazać dokumentację lub kod źródłowy, który to wskazuje?
Rob Bednark
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.