Comment supprimer une base de données PostgreSQL s'il y a des connexions actives?

je dois écrire un script qui supprimera une base de données PostgreSQL. Il y a peut-être beaucoup de connexions, mais le script devrait l'ignorer.

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

comment résoudre le problème?

514
demandé sur Kuberchaun 2011-03-23 19:03:36

10 réponses

ceci supprimera les connexions existantes sauf la vôtre:

Requête pg_stat_activity et obtenir le pid valeurs que vous voulez tuer, puis le problème SELECT pg_terminate_backend(pid int) .

PostgreSQL 9.2 et plus:

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 aurez déconnecté tout le monde, vous devrez déconnecter et lancer la base de données DROP commande à partir d'une connexion à partir d'une autre base de données alias pas celui que vous essayez de laisser tomber.

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

890
répondu Kuberchaun 2018-08-08 03:43:52

dans PostgreSQL 9.2 et au-dessus, 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 versions plus anciennes c'est la même chose, il suffit de changer pid en procpid . Pour déconnecter d'une base de données différente, il suffit de changer current_database() au nom de la base de données dont vous voulez déconnecter les utilisateurs.

vous pouvez vouloir REVOKE le CONNECT droit des utilisateurs de la base de données avant déconnecter les utilisateurs, sinon les utilisateurs vont juste continuer à se reconnecter et vous n'aurez jamais la chance de laisser tomber la base de données. Voir ce commentaire et la question qui lui est associée, Comment puis-je détacher tous les autres utilisateurs de la base de données .

si vous voulez simplement déconnecter les utilisateurs inactifs, voir cette question .

98
répondu Craig Ringer 2017-05-23 12:34:44

vous pouvez tuer toutes les connexions avant de laisser tomber la base de données en utilisant la fonction pg_terminate_backend(int) .

vous pouvez obtenir tous les retours en arrière 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 ne pouvez pas être connecté vous-même à cette base de données

25
répondu a_horse_with_no_name 2011-03-23 16:28:27

j'ai remarqué que postgres 9.2 appelle maintenant la colonne pid plutôt que procpid.

j'ai tendance à l'appeler du shell:

#!/usr/bin/env bash
# kill all connections to the postgres server
if [ -n "" ] ; then
  where="where pg_stat_activity.datname = ''"
  echo "killing all connections to database ''"
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

l'Espérance qui est utile. Merci à @JustBob pour le sql.

16
répondu kbrock 2012-10-23 03:35:17

selon votre version de postgresql, vous pourriez rencontrer un bug, qui fait pg_stat_activity pour omettre les connexions actives des utilisateurs abandonnés. Ces connexions ne sont pas non plus indiquées dans pgAdminIII.

si vous faites des tests automatiques (dans lesquels vous créez aussi des utilisateurs), cela pourrait ê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: En 9.2+ vous aurez une modification procpid à pid .

12
répondu jb. 2013-12-11 09:53:25

dans L'invite de commande Linux, j'arrêterais d'abord tous les processus postgresql qui tournent en liant cette commande sudo / etc / init.d / PostgreSQL redémarrage

, tapez la commande bg pour vérifier si d'autres processus postgresql sont toujours en cours

suivi de dropdb dbname pour supprimer la base de données

sudo /etc/init.d/postgresql restart
bg
dropdb dbname

Cela fonctionne pour moi sur linux invite de commande

7
répondu Maurice Elagu 2015-10-29 07:55:10

je viens de redémarrer le service à Ubuntu pour déconnecter les clients connectés.

sudo service postgresql stop
sudo service postgresql start

psql
DROP DATABASE DB_NAME;
6
répondu devdrc 2017-11-13 20:03:12

PostgreSQL 9.2 et plus:

SELECT pg_terminate_backend(pid)FROM pg_stat_activity WHERE datname = 'YOUR_DATABASE_NAME_HERE'

4
répondu Marcelo C. 2016-11-22 17:39:23

Voilà mon hack... = D

# Make sure no one can connect to this database except you!
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "UPDATE pg_database SET datallowconn=false WHERE datname='<DATABASE_NAME>';"

# Drop all existing connections except for yours!
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '<DATABASE_NAME>' AND pid <> pg_backend_pid();"

# Drop database! =D
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "DROP DATABASE <DATABASE_NAME>;"

j'ai mis cette réponse parce que inclure une commande (ci-dessus) pour bloquer les nouvelles connexions et parce que toute tentative avec la commande ...

REVOKE CONNECT ON DATABASE <DATABASE_NAME> FROM PUBLIC, <USERS_ETC>;

... ne fonctionne pas pour bloquer les nouvelles connexions!

merci à @araqnid @GoatWalker ! = D

https://stackoverflow.com/a/3185413/3223785

3
répondu Eduardo Lucio 2017-07-20 13:23:22

dans mon cas, j'ai dû exécuter une commande pour supprimer toutes les connexions, y compris ma connexion active administrateur

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE datname = current_database()

qui a mis fin à toutes les connexions et m'a montré une fatale "erreur" message:

FATAL: terminating connection due to administrator command SQL state: 57P01

après cela, il a été possible de supprimer la base de données

0
répondu Chtiwi Malek 2017-03-02 10:55:14