web-dev-qa-db-fra.com

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

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)

22
Rob Bednark

"Ç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 récupère suffisamment de lignes pour remplir son tampon d'envoi réseau, puis s'arrête et reste bloqué jusqu'à ce que la connexion TCP tombe, auquel cas elle va s'interrompre. S'il termine avant il remplit le TCP buffer d'envoi il se terminera avec succès, donc s'il est la validation automatique de 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 un segfault/crash client, SIGTERM, SIGKILL, etc.), le serveur PostgreSQL définissez l'indicateur d'interruption. La prochaine fois que la requête recherchera des interruptions lors de son exécution, elle verra l'indicateur et s'interrompra. 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 emplacements dans le cœur de PostgreSQL - auquel cas il pourrait ne pas remarquer l'interruption pendant une longue période et continuer à fonctionner. Il verra presque toujours l'interruption et abandonnera avant de terminer et de valider s'il s'agit d'un autocommit, cependant.

Si le client est tué par quelque chose comme un redémarrage soudain du système d'exploitation, de sorte que l'hôte client ne sait soudainement rien sur le TCP = connexion mais peut 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 l'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 autocommit, ou si votre requête était un COMMIT qui était en 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 s'il a commis ou non. 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 validation en deux phases et un gestionnaire de transactions côté client.

34
Craig Ringer

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.

2
jjanes