726 votes

Comment supprimer une base de données PostgreSQL si des connexions y sont actives ?

Je dois écrire un script qui abandonne une base de données PostgreSQL. Il peut y avoir beaucoup de connexions à celle-ci, mais le script doit l'ignorer.

La norme DROP DATABASE db_name La requête ne fonctionne pas lorsqu'il y a des connexions ouvertes.

Comment puis-je résoudre le problème ?

1 votes

Quelle version de PostgreSQL utilisez-vous ?

1 votes

Problème : Bien que vous puissiez tuer les sessions connectées à la base de données, elles peuvent se reconnecter si rapidement que vous ne pouvez toujours pas déposer la base de données. Heureusement, cet article montre comment verrouiller les nouvelles connexions, ce qui vous permet de tuer les connexions actuelles et de supprimer la base de données comme prévu : dba.stackexchange.com/questions/11893/

1 votes

J'ai trouvé cette réponse sur dba.stackexchange très utile. dba.stackexchange.com/a/11895/163539 -- succinct mais suffisamment explicatif.

1232voto

Bob Points 9217

Cela supprimera les connexions existantes, sauf la vôtre :

Requête pg_stat_activity et obtenez les valeurs de pid que vous voulez tuer, puis lancez SELECT pg_terminate_backend(pid int) à eux.

PostgreSQL 9.2 et supérieur :

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB' --  change this to your DB
  AND pid <> pg_backend_pid();

PostgreSQL 9.1 et inférieur :

SELECT pg_terminate_backend(pg_stat_activity.procpid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB' --  change this to your DB
  AND procpid <> pg_backend_pid();

Une fois que vous avez déconnecté tout le monde, vous devez vous déconnecter et lancer la commande DROP DATABASE à partir d'une connexion d'une autre base de données (pas celle que vous essayez de supprimer).

Notez le changement de nom de la procpid colonne à pid . Voir ce fil de la liste de diffusion .

13 votes

Et bien sûr, assurez-vous de le faire à partir d'une connexion à la base de données qui n'est pas une connexion à 'TARGET_DB', sinon vous obtenez 'ERROR'. Une connexion 'postgres' fonctionne bien.

0 votes

Fonctionne très bien, il faut juste se rappeler que vous ne pouvez pas être connecté à ce DB ! Utilisez Disconnect sur la base de données dans pgAdmin.

3 votes

En fait, il déconnecte les clients un par un, et si votre client se trouve au milieu de la liste, il sera également déconnecté. Par conséquent, certaines connexions resteront en vie. La bonne réponse est donc celle de Craig Ringer (voir ci-dessous). SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE datname = current_database() AND pg_stat_activity.pid <> pg_backend_pid() ;

134voto

Craig Ringer Points 72371

Dans PostgreSQL 9.2 et plus, pour déconnecter tout sauf votre session de la base de données à laquelle vous êtes connecté :

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE datname = current_database()
  AND pid <> pg_backend_pid();

Dans les anciennes versions, c'est la même chose, il suffit de modifier pid à procpid . Pour se déconnecter d'une autre base de données, il suffit de changer current_database() au nom de la base de données dont vous voulez déconnecter les utilisateurs.

Vous pouvez REVOKE le site CONNECT des utilisateurs de la base de données avant de déconnecter les utilisateurs, sinon les utilisateurs continueront à se reconnecter et vous n'aurez jamais la possibilité de supprimer la base de données. Voir ce commentaire et la question à laquelle elle est associée, Comment détacher tous les autres utilisateurs de la base de données ? .

Si vous souhaitez simplement déconnecter les utilisateurs inactifs, voir cette question .

3 votes

SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE datname = current_database() AND pg_stat_activity.pid <> pg_backend_pid() ;

27voto

a_horse_with_no_name Points 100769

Vous pouvez tuer toutes les connexions avant d'abandonner la base de données en utilisant la commande pg_terminate_backend(int) fonction.

Vous pouvez obtenir tous les backends en cours d'exécution en utilisant la vue système pg_stat_activity

Je ne suis pas tout à fait sûr, mais ce qui suit tuerait probablement toutes les sessions :

select pg_terminate_backend(procpid)
from pg_stat_activity
where datname = 'doomed_database'

Bien sûr, vous n'êtes peut-être pas connecté vous-même à cette base de données.

20voto

jb. Points 4932

En fonction de votre version de postgresql, vous pouvez rencontrer un bug, qui rend pg_stat_activity pour omettre les connexions actives des utilisateurs abandonnés. Ces connexions ne sont pas non plus affichées dans pgAdminIII.

Si vous effectuez des tests automatiques (dans lesquels vous créez également des utilisateurs), cela peut être un scénario probable.

Dans ce cas, vous devez revenir à des requêtes comme :

 SELECT pg_terminate_backend(procpid) 
 FROM pg_stat_get_activity(NULL::integer) 
 WHERE datid=(SELECT oid from pg_database where datname = 'your_database');

NOTE : Dans la version 9.2+, vous devrez modifier procpid à pid .

1 votes

C'est ce que je cherchais mais pour (en supposant 9.2 et plus) vous devez supprimer la référence à pg_stat_activity et changer procpid en pid.

2 votes

Après avoir changé procpid à pid ce snippet fonctionne sur 9.3.

0 votes

même sans supprimer pg_stat_activity ? J'obtenais une erreur en 9.2

17voto

kbrock Points 328

J'ai remarqué que postgres 9.2 appelle désormais la colonne pid plutôt que procpid.

J'ai tendance à l'appeler depuis la coquille :

#!/usr/bin/env bash
# kill all connections to the postgres server
if [ -n "$1" ] ; then
  where="where pg_stat_activity.datname = '$1'"
  echo "killing all connections to database '$1'"
else
  echo "killing all connections to database"
fi

cat <<-EOF | psql -U postgres -d postgres 
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
${where}
EOF

J'espère que cela vous sera utile. Merci à @JustBob pour le sql.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X