zabij -9 proces postgres

25

Zapytanie SELECT postgres wymknęło się spod kontroli na naszym serwerze DB i zaczęło zjadać mnóstwo pamięci i zamieniać się, dopóki serwerowi zabrakło pamięci. Znalazłem konkretny proces za pośrednictwem ps aux | grep postgresi uruchomiłem kill -9 pid. To zabiło proces i pamięć została zwolniona zgodnie z oczekiwaniami. Reszta systemu i zapytania postgres wydawały się być nienaruszone. Na tym serwerze działa postgres 9.1.3 na SLES 9 SP4.

Jednak jeden z naszych programistów żuł mnie za zabicie procesu postgres kill -9, mówiąc, że usunie całą usługę postgres. W rzeczywistości tak nie było. Robiłem to już kilka razy i nie widziałem żadnych negatywnych skutków ubocznych.

To powiedziawszy, a po dalszym czytaniu wygląda na to, że kill pidbez flag jest preferowanym sposobem na zabicie niekontrolowanego procesu postgres, ale dla innych użytkowników społeczności postgres wydaje się również, że postgres „poprawił się” przez lata, tak że kill -9na pojedynczy proces zapytania / wątek nie jest już wyrokiem śmierci.

Czy ktoś może oświecić mnie na temat właściwego sposobu zabicia niekontrolowanego procesu postgres, a także tego, jak katastrofalne (lub łagodne) kill -9jest używanie Postgres w dzisiejszych czasach? Dzięki za wgląd.

Banjer
źródło

Odpowiedzi:

31

voretaq7 „s odpowiedź obejmuje główne punkty, w tym właściwej drodze wypowiedzenia backendów ale chciałbym dodać trochę więcej wyjaśnień.

kill -9(tj. SIGKILL) nigdy nie powinno być nigdy pierwszym wyborem domyślnym . Powinno to być ostatnią deską ratunku, gdy proces nie odpowiada na normalne żądania zamknięcia, a funkcja SIGTERM( kill -15) nie ma wpływu. Dotyczy to Pg i prawie wszystkiego innego.

kill -9 nie daje zabitemu procesowi żadnej szansy na jakiekolwiek czyszczenie.

Jeśli chodzi o PostgreSQL, Pg widzi kopię zapasową zakończoną przez kill -9awarię kopii zapasowej . Wie, że backend mógł uszkodzić pamięć współużytkowaną - ponieważ mógłbyś ją przerwać w połowie, na przykład, zapisując stronę w shm lub modyfikując jedną - więc kończy i uruchamia wszystkie pozostałe backendy, gdy zauważy, że backend nagle zniknął i zakończony niezerowym kodem błędu.

Zostanie to zgłoszone w dziennikach.

Jeśli wydaje się, że nie wyrządza to szkody, to dlatego, że Pg restartuje wszystko po awarii, a twoja aplikacja odzyskuje utracone połączenia. To nie jest dobry pomysł. Jeśli żadne inne awarie backendu nie są tak dobrze przetestowane, jak normalnie działające części Pg i są znacznie bardziej skomplikowane / zróżnicowane, więc szanse na błąd czający się w obsłudze awarii backend i odzyskiwaniu są wyższe.

BTW, jeśli jesteś kill -9postmasterem, usuń go postmaster.pidi uruchom ponownie, nie upewniając się, że postgresnie ma już wszystkich backendów, mogą się zdarzyć bardzo złe rzeczy . Może się to łatwo zdarzyć, jeśli przypadkowo zabijesz postmastera zamiast backendu, zobaczysz, że baza danych uległa awarii, spróbujesz go zrestartować, usuniesz „przestarzały” plik .pid, gdy restart się nie powiedzie, i spróbujesz go ponownie uruchomić. To jeden z powodów, dla których powinieneś unikać machania kill -9wokół Pg i nie należy go usuwać postmaster.pid.

Demonstracja:

Aby zobaczyć dokładnie, co dzieje się, gdy masz kill -9backend, wypróbuj te proste kroki. Otwórz dwa terminale, otwórz psql w każdym i w każdym przebiegu SELECT pg_backend_pid();. Na innym terminalu kill -9jeden z PID. Teraz uruchom SELECT pg_backend_pid();ponownie obie sesje psql. Zauważ, jak oboje stracili połączenie?

Sesja 1, którą zabiliśmy:

$ psql regress
psql (9.1.4)
Type "help" for help.

regress=# select pg_backend_pid();
 pg_backend_pid 
----------------
           6357
(1 row)

[kill -9 of session one happens at this point]

regress=# select pg_backend_pid();
server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.
regress=# select pg_backend_pid();
 pg_backend_pid 
----------------
           6463
(1 row)

Sesja 2, która była uszkodzeniem dodatkowym:

$ psql regress
psql (9.1.4)
Type "help" for help.

regress=# select pg_backend_pid();
 pg_backend_pid 
----------------
           6283
(1 row)

[kill -9 of session one happens at this point]

regress=# select pg_backend_pid();
WARNING:  terminating connection because of crash of another server process
DETAIL:  The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
HINT:  In a moment you should be able to reconnect to the database and repeat your command.
server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.
regress=# select pg_backend_pid();
 pg_backend_pid 
----------------
           6464
(1 row)

Zobacz, jak zostały przerwane obie sesje? Dlatego nie masz kill -9backendu.

Craig Ringer
źródło
1
Wszystkie bardzo dobre odpowiedzi tutaj i bardzo pokorne mogę dodać. Mógłbym oznaczyć je wszystkie jako zaakceptowane, ale @Craig Ringer ma tutaj dodatkowe punkty i naprawdę napędza to. Jeszcze raz dziękuję SF za oczyszczenie mnie z moich złych nawyków!
Banjer,
2
@Craig: Co za wspaniała odpowiedź; i dołączając demonstrację, chciałbym móc zagłosować 100x. Jestem programistą, który codziennie pracuje z PG i od 6.x dni, a Twoja odpowiedź jest natychmiastowa! Miły!
Kilo
2
Niezła odpowiedź. Dodatek: jeśli masz proces zaplecza, który absolutnie nie umrze - nie z pg_terminate_backend, nie z restartem stosu serwera, bez niczego, możesz go zabić, jak chcesz, ale upewnij się, że masz działającą kopię zapasową bazy danych. Możesz to zrobić na kilka sposobów: możesz użyć pg_basebackuplub podobnie (lub po prostu rsynci pg_start\stop_backup), aby wykonać kopię zapasową katalogu danych (przetestuj kopie zapasowe przed kontynuowaniem!), Lub możesz użyć pg_dump[all]do odzyskania danych. Tylko wtedy powinieneś rozważyć kill -9ponowne uruchomienie komputera lub cokolwiek innego.
Zac B
1
@ZacB Tak, a jeśli go zabijesz, upewnij się, że wszystkie backendy umierają. Przede wszystkim nigdy nie usuwaj postmaster.pid. Zawsze.
Craig Ringer,
29

I found the particular process via ps aux | grep postgres and ran kill -9 pid.
NIE! ZŁY! KROK Z DALA OD BACKENDU!

Poważnie - nie zabijaj backendów Postgres w ten sposób - OKOLICZNE rzeczy mogą się zdarzyć (nawet przy wszystkich ulepszeniach stabilności, które zostały wprowadzone od 7.x dni), które mogą zniszczyć całą bazę danych, a deweloper ma rację jesteś za robienie tego.

Istnieje w rzeczywistości błogosławiony i zatwierdzony sposób robienia tego z poziomu Postgres - jest nawet w podręczniku Postgres, choć ten post SO lepiej wyjaśnia to ...

SELECT pg_cancel_backend(pid)
Wysyła sygnał cancel ( SIGINT) do określonego backendu, który anuluje aktualnie uruchomione zapytanie.

select pg_terminate_backend(pid)
Wysyła sygnał terminate ( SIGTERM) do określonego backendu, który anuluje zapytanie i przerywa backend (przerywa połączenie).

Identyfikatory zaplecza można uzyskać z pg_stat_activitytabeli (lub ps)

voretaq7
źródło
4
W przypadku, gdy ktoś zastanawia się nad okropnymi rzeczami, biorąc pod uwagę, że kill -9nie jest to podobne do nagle wyłączania systemu, jeśli chodzi o zabity proces: Pg jest bardzo tolerancyjny dla awarii zaplecza (jak a kill -9) i nigdy nie powinno być uszkodzenia danych. Nie będzie mieć korupcji jeśli zabić postmaster'a wyjmij postmaster.pid i zrestartować go również bez zabijania każdego backend pierwszy. Że będzie zniszczyć bazę danych, ale zajmuje dużo więcej niż tylko kill -9do zaplecza. kill -9nie daje postmasterowi czasu na zabicie backendów, dlatego jest to niebezpieczne.
Craig Ringer,
2
... jak sprawa z konsultacją w nagłych wypadkach, którą miałem w zeszłym tygodniu. Poważnie uszkodzona baza danych, utrata dwóch dni pracy, ponieważ ich kopie zapasowe zawiodły (i nie przeprowadziły automatycznego testowania przywracania), nie działały przez 48 godzin. Nie należy usuwać postmaster.pid.
Craig Ringer
8

Zabicie procesu klienta PostgreSQL powinno być w porządku. Zabicie procesu demona PostgreSQL może Cię skarcić.

Ponieważ demony SQL mają również wewnętrzne sterowanie procesem, preferowanym sposobem jest najpierw spróbowanie użycia tego kanału.

Zobacz Zatrzymaj (długie) uruchomione zapytanie SQL w PostgreSQL ... z StackOverflow.

Jeff Ferland
źródło
4
kill -9i tak nigdy nie powinno być domyślnym wyborem, jest to ostateczność. Wyślij SIGTERMz kill -TERMlub zwykły, killa jeśli odbiorca nie odpowie po pewnym czasie, tylko wtedy powinieneś rozważyć kill -KILL( kill -9).
Craig Ringer