web-dev-qa-db-fra.com

Heroku Postgres - met fin à la requête bloquée (inactif dans la transaction)

J'utilise Heroku avec l'option Crane Postgres et j'exécutais une requête sur la base de données à partir de ma machine locale lorsque ma machine locale est tombée en panne. Si je cours

select * from pg_stat_activity

une des entrées a

<IDLE> in transaction

dans la colonne current_query_text.

En conséquence, je ne peux pas supprimer la table sur laquelle était écrite la requête terminée. J'ai essayé d'utiliser pg_cancel_backend (N) et renvoie True, mais rien ne semble se produire.

Comment puis-je mettre fin à ce processus pour pouvoir laisser tomber la table?

88
alan

Ceci est une réponse générale de Postgres, et non spécifique à heroku


(La réponse simple-stupide à cette question peut être ... redémarrez simplement postgresql. En supposant que ce ne soit pas souhaitable ou non une option ...)

Trouvez le PID en exécutant ce sql:

SELECT pid , query, * from pg_stat_activity
  WHERE state != 'idle' ORDER BY xact_start;

(Les anciennes versions de Postgres utilisent procpid plutôt que pid). Vous trouverez le pid dans la première colonne (à gauche) et la première ligne (en haut) correspondra probablement à la requête que vous souhaitez terminer. Je suppose que le pid est 1234 ci-dessous.

Vous pouvez annuler une requête via SQL (c'est-à-dire sans accès à Shell) tant qu'elle vous appartient ou que vous disposez d'un accès super-utilisateur:

select pg_cancel_backend(1234);

C'est la méthode "douce" ... la requête ne disparaîtra pas immédiatement. Si cela ne fonctionne pas, utilisez ceci à la place:

select pg_terminate_backend(1234);

Si vous disposez d'un accès Shell et d'autorisations root ou postgres, vous pouvez également le faire à partir du shell:

kill -INT 1234

Si cela ne vous aide pas, utilisez:

kill 1234

NE PAS:

kill -9 1234

... le serveur postgres entier sera souvent mis à feu, vous pourrez alors aussi redémarrer postgres. Postgres est assez robuste, donc les données ne seront pas corrompues, mais je déconseillerais d'utiliser "kill -9" dans tous les cas :-)


Une "transaction inactive" durable signifie souvent que la transaction n'a pas été clôturée par un "commit" ou un "rollback", ce qui signifie que l'application est défectueuse ou n'est pas conçue pour fonctionner avec des bases de données transactionnelles. Il faut éviter les "transactions inactives" de longue durée, car elles peuvent également entraîner de graves problèmes de performances.

124
tobixen

Essaye ça:

select pg_terminate_backend(pid int)

Plus à ce sujet, vous pouvez trouver ici . Cela devrait être une solution plus "propre" de ce problème que le processus de destruction par système.

36
evgenek

Vous pouvez installer le module complémentaire heroku-pg-extras et exécuter la commande suivante pour obtenir le PID:

heroku pg:locks --app <your-app>

Alors juste faire:

heroku pg:kill <pid> --app <your-app> 

[~ # ~] note [~ # ~] : L'option --force peut être utilisée pour lancer pg_terminate_backend qui supprime toute la connexion pour cette question.

Si heroku pg:locks Ne répertorie rien, essayez heroku pg:ps.

Pour plus d'informations, consultez:
https://devcenter.heroku.com/articles/heroku-postgresql#pg-ps-pg-kill-pg-killall

19
davidfrancisco

Nous pouvons utiliser les éléments suivants pour y parvenir en une seule requête:

SELECT pg_cancel_backend(pid), pg_terminate_backend(pid) FROM pg_stat_activity WHERE state != 'idle';
0
codersofthedark