web-dev-qa-db-fra.com

Postgresql - impossible de supprimer la base de données en raison de certaines connexions automatiques à la base de données

Chaque fois que j'essaie de supprimer une base de données, je reçois:

ERROR:  database "pilot" is being accessed by other users
DETAIL:  There is 1 other session using the database.

Quand j'utilise:

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB';

J'ai mis fin à la connexion à partir de cette base de données, mais si j'essaie de supprimer la base de données, quelqu'un se connecte automatiquement à cette base de données et donne cette erreur. Qu'est-ce qui pourrait faire ça? Personne n'utilise cette base de données, sauf moi.

91
Andrius

Vous pouvez empêcher de futures connexions:

REVOKE CONNECT ON DATABASE thedb FROM public;

(et éventuellement d'autres utilisateurs/rôles; voir \l+ dans psql)

Vous pouvez alors mettre fin à toutes les connexions à cette base de données, sauf la vôtre:

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

Sur les anciennes versions, pid s'appelait procpid, vous devrez donc vous en occuper.

Puisque vous avez révoqué les droits CONNECT, tout ce qui essayait de se connecter automatiquement ne devrait plus pouvoir le faire.

Vous pourrez maintenant supprimer la base de données.

Cela ne fonctionnera pas si vous utilisez des connexions superutilisateur pour des opérations normales, mais si vous le faites, vous devez d'abord résoudre ce problème.

98
Craig Ringer

Chaque fois que j'essaie de supprimer une base de données, je reçois:

ERROR:  database "pilot" is being accessed by other users
DETAIL:  There is 1 other session using the database.

Vous devez d'abord révoquer

REVOKE CONNECT ON DATABASE TARGET_DB FROM public;

Alors utilisez:

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB';

Cela fonctionnera sûrement.

77
Suneel Kumar

Il suffit de vérifier quelle est la connexion, d'où elle vient. Vous pouvez voir tout cela dans:

select * from pg_stat_activity where datname = 'TARGET_DB';

C'est peut-être votre connexion?

22
user80168

J'ai trouvé une solution à ce problème essayez d'exécuter cette commande en terminal

ps -ef | grep postgres

tuer le processus par cette commande 

Sudo kill -9 PID
19
Dinesh Pallapa

Cela signifie qu'un autre utilisateur accède à la base de données ... Redémarrez simplement le postgresql. Cette commande fera l'affaire

root@kalilinux:~#Sudo service postgresql restart

Puis essayez de déposer la base de données:

postgres=# drop database test_database

Ça fera l'affaire. Bonne codage

11
Suman Astani

Si aucun impact potentiel sur les autres services de votre ordinateur, service postgresql restart

8
ScotchAndSoda

pgAdmin 4 solution en utilisant l'interface utilisateur

Commencez par activer l'activité d'affichage sur le tableau de bord si vous n'avez pas:

File > Preferences > Dashboards > Display > Show Activity > true

Désactivez maintenant tous les processus utilisant la base de données:

  1. Cliquez sur le nom de la base de données
  2. Cliquez sur Tableau de bord> Sessions
  3. Cliquez sur l'icône Actualiser
  4. Cliquez sur l'icône de suppression (x) à côté de chaque processus pour y mettre fin.

Devrait maintenant pouvoir supprimer la base de données.

5
Andrew

Dans mon cas, j'utilise AWS Redshift (basé sur Postgres) . Et il semble qu'il n'y ait pas d'autres connexions à la base de données, mais j'obtiens la même erreur.

ERROR:  database "XYZ" is being accessed by other users

Dans mon cas, il semble que le cluster de base de données effectue encore certains traitements sur la base de données et, bien qu'il n'y ait aucune autre connexion externe/utilisateur, la base de données est toujours utilisée en interne. J'ai trouvé cela en exécutant ce qui suit:

SELECT * FROM stv_sessions;

Donc, mon hack était d'écrire une boucle dans mon code, en recherchant les lignes contenant le nom de ma base de données. (bien sûr, la boucle n'est pas infinie, et est une boucle assoupie, etc.)

SELECT * FROM stv_sessions where db_name = 'XYZ';

Si des lignes sont trouvées, supprimez chaque PID, un par un.

SELECT pg_terminate_backend(PUT_PID_HERE);

Si aucune ligne trouvée, continuez pour supprimer la base de données

DROP DATABASE XYZ;

Remarque: Dans mon cas, j'écris des tests d'unité/système Java, dans lesquels cela pourrait être considéré comme acceptable. Ce n'est pas acceptable pour le code de production.


Voici le hack complet, en Java (ignorer mes classes de test/utilitaire).

  int i = 0;
  while (i < 10) {
    try {
      i++;
      logStandardOut("First try to delete session PIDs, before dropping the DB");
      String getSessionPIDs = String.format("SELECT stv_sessions.process, stv_sessions.* FROM stv_sessions where db_name = '%s'", dbNameToReset);
      ResultSet resultSet = databaseConnection.execQuery(getSessionPIDs);
      while (resultSet.next()) {
        int sessionPID = resultSet.getInt(1);
        logStandardOut("killPID: %s", sessionPID);
        String killSessionPID = String.format("select pg_terminate_backend(%s)", sessionPID);
        try {
          databaseConnection.execQuery(killSessionPID);
        } catch (DatabaseException dbEx) {
          //This is most commonly when a session PID is transient, where it ended between my query and kill lines
          logStandardOut("Ignore it, you did your best: %s, %s", dbEx.getMessage(), dbEx.getCause());
        }
      }

      //Drop the DB now
      String dropDbSQL = String.format("DROP DATABASE %s", dbNameToReset);
      logStandardOut(dropDbSQL);
      databaseConnection.execStatement(dropDbSQL);
      break;
    } catch (MissingDatabaseException ex) {
      //ignore, if the DB was not there (to be dropped)
      logStandardOut(ex.getMessage());
      break;
    } catch (Exception ex) {
      logStandardOut("Something went wrong, sleeping for a bit: %s, %s", ex.getMessage(), ex.getCause());
      sleepMilliSec(1000);
    }
  }
2
Sagan

Aussi simple que cela

Sudo service postgresql restart
2
OdkoPP

Même si j’ai trouvé les deux réponses top-votées utiles à d’autres occasions, aujourd’hui, le moyen le plus simple de résoudre le problème était de réaliser que PyCharm pouvait garder une session ouverte. Si je cliquais sur Stop dans PyCharm, cela pourrait aider. Avec pgAdmin4 ouvert dans le navigateur, je l’ai fait et j'ai presque immédiatement vu les statistiques des sessions de la base de données tomber à 0, ce qui m'a permis de supprimer la base de données.

1
hlongmore

Solution:
1. Arrêtez le serveur Pg
 enter image description here
2. Il déconnectera toutes les connexions actives
3. Redémarrer le serveur pg
4. Essayez votre commande

1
amoljdv06

En terminal essayez cette commande:

ps -ef | grep postgres

vous verrez comme: 

501 1445 3645 0 00:05 0: 00.03 postgres: sasha nombase [local] inactif

Le troisième numéro (3645) est PID. 

Vous pouvez supprimer ceci 

Sudo kill -9 3645

Et après cela, démarrez votre connexion PostgreSQL.

Démarrer manuellement:

pg_ctl -D /usr/local/var/postgres start
0
Alexandr