Une requête Postgres de longue durée est-elle abandonnée si la connexion est perdue / interrompue?

21

Si j'ouvre une connexion à Postgres et émets une requête de longue durée, puis que je coupe la connexion (par exemple, tue le processus client qui a ouvert la connexion), la requête de longue durée continuera-t-elle à s'exécuter ou sera-t-elle automatiquement abandonnée? Est-ce configurable?

(J'utilise Postgresql 9.2.9)

Rob Bednark
la source

Réponses:

32

"Ça dépend".

Si le client disparaît en raison de la perte de connexion réseau, la requête s'exécute généralement jusqu'à ce qu'il ait récupéré suffisamment de lignes pour remplir son tampon d'envoi réseau, puis s'arrête et reste bloqué jusqu'à ce que la connexion TCP cesse, à quel point elle s'arrêtera. S'il se termine avant de remplir le tampon d'envoi TCP, il se terminera avec succès, donc s'il est validé automatiquement, la requête sera validée.

Si le client est tué d'une manière que le système d'exploitation du client peut signaler au serveur via un TCP RST (comme une panne / panne client, SIGTERM, SIGKILL, etc.), le serveur PostgreSQL définira l'indicateur d'interruption. La prochaine fois que la requête vérifie les interruptions lors de son exécution, elle verra l'indicateur et abandonnera. Parfois, une requête peut effectuer un travail gourmand en CPU dans du code qui ne vérifie pas les interruptions - certaines extensions et quelques endroits dans le cœur de PostgreSQL - auquel cas elle peut ne pas remarquer l'interruption pendant longtemps et continuer de fonctionner. Cependant, il verra presque toujours l'interruption et abandonnera avant de terminer et de valider s'il s'agit d'un autocommit.

Si le client est tué par quelque chose comme un redémarrage soudain du système d'exploitation, afin que l' hôte client ne sache soudainement rien sur la connexion TCP mais puisse toujours répondre sur le réseau, la requête sera probablement abandonnée la première fois qu'elle essaiera d'écrire une ligne, comme Jeff a dit, car l'hôte du client enverra un TCP RST en réponse au premier paquet envoyé par le serveur après le redémarrage. PostgreSQL vérifie les interruptions à chaque ligne qu'il envoie.

Ce comportement n'est pas configurable. En ce qui concerne PostgreSQL, si le client s'en va, son travail consiste à mettre fin à toutes les requêtes que le client exécutait. Pour changer cela, vous auriez besoin d'une sorte de jeton d'achèvement de requête que vous pourriez obtenir au démarrage de la requête, puis utilisez pour interroger le serveur sur la requête via une autre connexion plus tard. Essentiellement, vous devez implémenter des requêtes asynchrones / en arrière-plan. Peut-être une fonctionnalité intéressante, mais non prise en charge actuellement.

Si la requête est à validation automatique, ou si votre requête était COMMITen cours au moment où vous avez tué le client / perdu la connexion, il est possible qu'une transaction soit dans un état indéterminé où le client ne sait pas si ou pas engagé. Il n'y a pas de véritable moyen de le savoir, à part rechercher les effets de la transaction sur les données.

Lorsque cela est inacceptable, vous pouvez utiliser la validation en deux phases et un gestionnaire de transactions côté client.

Craig Ringer
la source
1
Wow, juste ce que je cherchais, une excellente réponse détaillée! Merci @Craig_Ringer!
Rob Bednark
2

Il continuera à s'exécuter jusqu'à ce qu'il essaie de renvoyer des lignes à la connexion et détecte la rupture. Donc, pour une requête qui fait tout le travail avant de retourner des lignes, elle s'exécutera essentiellement jusqu'à son terme.

jjanes
la source
Merci @jjanes. Pouvez-vous indiquer une documentation ou un code source qui l'indique?
Rob Bednark