tuer -9 un processus postgres

25

Une requête SELECT postgres est devenue incontrôlable sur notre serveur de base de données et a commencé à consommer des tonnes de mémoire et à échanger jusqu'à ce que le serveur manque de mémoire. J'ai trouvé le processus particulier via ps aux | grep postgreset j'ai couru kill -9 pid. Cela a tué le processus et la mémoire libérée comme prévu. Le reste du système et les requêtes postgres ne semblent pas être affectés. Ce serveur exécute postgres 9.1.3 sur SLES 9 SP4.

Cependant, l'un de nos développeurs m'a critiqué pour avoir tué un processus postgres avec kill -9, disant qu'il allait supprimer tout le service postgres. En réalité, ce n'était pas le cas. J'ai fait cela avant une poignée de fois et je n'ai vu aucun effet secondaire négatif.

Cela dit, et après une lecture plus approfondie, il semble que kill pidsans les drapeaux soit le moyen préféré de tuer un processus de postgres incontrôlable, mais pour d'autres utilisateurs de la communauté postgres, il semble également que postgres s'est "amélioré" au fil des ans, de sorte que kill -9sur un processus de requête / thread individuel n'est plus une condamnation à mort.

Quelqu'un peut-il m'éclairer sur la bonne façon de tuer un processus de postgres incontrôlable ainsi que sur la façon dont l'utilisation désastreuse (ou bénigne) kill -9est avec Postgres de nos jours? Merci pour la perspicacité.

Banjer
la source

Réponses:

31

La réponse de voretaq7 couvre les points clés, y compris la bonne façon de terminer les backends, mais je voudrais ajouter un peu plus d'explications.

kill -9(c.-à-d. SIGKILL) ne devrait jamais, jamais, jamais être votre premier choix par défaut . Cela devrait être votre dernier recours lorsque le processus ne répond pas à ses demandes d'arrêt normales et qu'un SIGTERM( kill -15) n'a eu aucun effet. C'est vrai pour Pg et à peu près tout le reste.

kill -9 ne donne aucune chance au processus tué de faire un nettoyage.

En ce qui concerne PostgreSQL, Pg voit un sauvegardé qui se termine par kill -9un crash sauvegardé . Il sait que le backend a peut-être corrompu la mémoire partagée - parce que vous auriez pu l'interrompre à mi-chemin en écrivant une page dans shm ou en en modifiant un, par exemple - donc il termine et redémarre tous les autres backends quand il remarque qu'un backend a soudainement disparu et est sorti avec un code d'erreur non nul.

Vous verrez cela signalé dans les journaux.

Si cela ne semble pas faire de mal, c'est parce que Pg redémarre tout après le crash et que votre application se rétablit proprement des connexions perdues. Cela n'en fait pas une bonne idée. Si rien d'autre n'est bloqué, les tests backend sont moins bien testés que les parties de Pg fonctionnant normalement et sont beaucoup plus compliqués / variés, donc les chances d'un bug qui se cache dans la gestion et la récupération des crashs backend sont plus élevées.

BTW, si vous kill -9le postmaster puis supprimez postmaster.pidet redémarrez sans vous assurer que chaque postgresbackend a disparu, de très mauvaises choses peuvent se produire . Cela peut facilement se produire si vous avez accidentellement tué le maître de poste au lieu d'un serveur principal, vu que la base de données était en panne, essayé de la redémarrer, supprimé le fichier .pid "périmé" lorsque le redémarrage a échoué et essayé de la redémarrer à nouveau. C'est l'une des raisons pour lesquelles vous devriez éviter de faire signe kill -9à Pg et ne pas supprimer postmaster.pid.

Une démonstration:

Pour voir exactement ce qui se passe lorsque vous êtes kill -9un backend, essayez ces étapes simples. Ouvrez deux terminaux, ouvrez psql dans chacun et à chaque exécution SELECT pg_backend_pid();. Dans un autre terminal, l' kill -9un des PID. Maintenant, exécutez SELECT pg_backend_pid();à nouveau dans les deux sessions psql. Remarquez comment ils ont tous deux perdu leurs connexions?

Session 1, que nous avons tuée:

$ 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)

Session 2, qui portait sur les dommages collatéraux:

$ 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)

Vous voyez comment les deux sessions ont été interrompues? C'est pourquoi vous n'avez pas de kill -9backend.

Craig Ringer
la source
1
Toutes les très bonnes réponses ici, et très humble je pourrais ajouter. Je pourrais tous les marquer comme acceptés, mais @Craig Ringer a quelques points supplémentaires ici et le pousse vraiment à la maison. Merci encore SF de m'avoir nettoyé de mes mauvaises habitudes!
Banjer
2
@Craig: Quelle superbe réponse; et pour inclure une démonstration, je souhaite pouvoir voter jusqu'à 100x. Je suis un développeur de logiciels qui travaille quotidiennement avec PG et depuis les jours 6.x et votre réponse est parfaite! Agréable!
Kilo
2
Bonne réponse. Un addendum: si vous avez un processus backend qui ne mourra absolument pas - pas avec pg_terminate_backend, pas avec un redémarrage de la pile du serveur, pas avec quoi que ce soit, vous pouvez le tuer comme vous le souhaitez, mais assurez-vous d'avoir une sauvegarde de travail de votre base de données. Vous pouvez le faire de deux manières: vous pouvez utiliser pg_basebackupou similaire (ou simplement rsyncet pg_start\stop_backup) pour sauvegarder votre répertoire de données (tester les sauvegardes avant de continuer!), Ou vous pouvez utiliser pg_dump[all]pour récupérer vos données. C'est seulement alors que vous devriez envisager kill -9, ou un redémarrage, ou autre chose.
Zac B
1
@ZacB Oui, et si vous le tuez, assurez-vous que tous les backends meurent. Plus important encore, ne supprimez jamaispostmaster.pid . Déjà.
Craig Ringer
29

I found the particular process via ps aux | grep postgres and ran kill -9 pid.
NON! MAUVAIS! Éloignez-vous du backend!

Sérieusement - Ne tuez pas les backends Postgres comme ça - des choses TERRIBLES peuvent se produire (même avec toutes les améliorations de stabilité qui ont été apportées depuis les jours 7.x) qui peuvent détruire toute votre base de données, et votre développeur a tout à fait raison de mâcher vous pour faire cela.

Il y a, en fait, une manière bénie et approuvée de le faire à partir de Postgres - C'est même dans le manuel de Postgres bien que SO post fasse un meilleur travail pour l'expliquer ...

SELECT pg_cancel_backend(pid)
Envoie un SIGINTsignal cancel ( ) au backend spécifié, ce qui annule la requête en cours d'exécution.

select pg_terminate_backend(pid)
Envoie un SIGTERMsignal terminate ( ) au backend spécifié, ce qui annule la requête et abandonne le backend (abandon de sa connexion).

Les ID de backend peuvent être obtenus à partir de la pg_stat_activitytable (ou ps)

voretaq7
la source
4
Au cas où quelqu'un s'interrogerait sur les choses terribles, étant donné que cela kill -9n'est pas différent de mettre soudainement le système hors tension en ce qui concerne le processus tué: Pg est très tolérant aux plantages de backend (comme a kill -9) et il ne devrait jamais y avoir de corruption de données. Il y aura corruption si vous tuez le postmaster , supprimez postmaster.pid et redémarrez-le sans tuer également chaque backend en premier. Cela va détruire votre base de données, mais prend beaucoup plus qu'un simple kill -9à un back - end. kill -9ne donne pas le temps au maître de poste de tuer les backends, c'est pourquoi c'est dangereux.
Craig Ringer
2
... comme un cas de consultation d'urgence que j'avais eu la semaine dernière. Gravement corrompu leur base de données, perdu deux jours de travail en raison de l'échec de leurs sauvegardes (et ils n'ont pas testé automatiquement leurs restaurations), ont été arrêtés pendant 48 heures. Ne supprimez pas postmaster.pid.
Craig Ringer
8

Tuer un processus client PostgreSQL devrait être correct. Tuer un processus de démon PostgreSQL pourrait vous faire gronder.

Étant donné que les démons SQL disposent également de contrôles de processus internes, la méthode préférée consiste à essayer d'utiliser ce canal en premier.

Voir Arrêter (longtemps) l'exécution d'une requête SQL dans PostgreSQL ... à partir de StackOverflow.

Jeff Ferland
la source
4
kill -9ne devrait jamais être votre choix par défaut de toute façon, c'est un dernier recours. Envoyez un SIGTERMavec kill -TERMou en clair killet si le destinataire ne répond pas après un certain temps, alors seulement vous devriez considérer kill -KILL( kill -9).
Craig Ringer