789 Stimmen

Wie kann man eine PostgreSQL-Datenbank löschen, wenn es aktive Verbindungen zu ihr gibt?

Ich muss ein Skript schreiben, das eine PostgreSQL-Datenbank löschen soll. Es kann viele Verbindungen zu ihr geben, aber das Skript sollte das ignorieren.

Die Norm DROP DATABASE db_name Die Abfrage funktioniert nicht, wenn es offene Verbindungen gibt.

Wie kann ich das Problem lösen?

1 Stimmen

Mit welcher Version von PostgreSQL arbeiten Sie?

2 Stimmen

Problem: Sie können zwar die mit der Datenbank verbundenen Sitzungen beenden, aber sie können sich so schnell wieder verbinden, dass Sie die Datenbank trotzdem nicht löschen können. Glücklicherweise zeigt dieser Beitrag, wie man neue Verbindungen sperrt, so dass man die aktuellen Verbindungen beenden und die Datenbank wie geplant löschen kann: dba.stackexchange.com/questions/11893/

1 Stimmen

Ich fand diese Antwort auf dba.stackexchange sehr hilfreich dba.stackexchange.com/a/11895/163539 -- kurz und bündig, aber ausreichend erklärend.

1336voto

Kuberchaun Punkte 27481

Dadurch werden alle bestehenden Verbindungen außer der Ihren gelöscht:

Abfrage pg_stat_activity und erhalten Sie die Pid-Werte, die Sie töten wollen, dann geben Sie SELECT pg_terminate_backend(pid int) zu ihnen.

PostgreSQL 9.2 und höher:

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 und niedriger:

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();

Sobald Sie alle Verbindungen getrennt haben, müssen Sie die Verbindung trennen und den Befehl DROP DATABASE von einer Verbindung zu einer anderen Datenbank aus eingeben, die nicht diejenige ist, die Sie löschen wollen.

Beachten Sie die Umbenennung der procpid Spalte zu pid . Siehe dieses Thema der Mailingliste .

16 Stimmen

Achten Sie natürlich darauf, dass Sie dies von einer Datenbankverbindung aus tun, die keine Verbindung zu "TARGET_DB" ist, sonst erhalten Sie "ERROR". Eine 'postgres'-Verbindung funktioniert gut.

0 Stimmen

Funktioniert prima, man muss nur daran denken, dass man nicht mit dieser DB verbunden werden kann! Verwenden Sie Disconnect für die Datenbank in pgAdmin.

3 Stimmen

Eigentlich würde die Verbindung zu einem Kunden nach dem anderen unterbrochen werden, und wenn Ihr Kunde in der Mitte der Liste steht, wird er auch unterbrochen. Infolgedessen werden einige Verbindungen bestehen bleiben. Die richtige Antwort ist also b

150voto

Craig Ringer Punkte 280068

In PostgreSQL 9.2 und höher, um alles außer Ihrer Sitzung von der Datenbank, mit der Sie verbunden sind, zu trennen:

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

In älteren Versionen ist es dasselbe, ändern Sie einfach pid zu procpid . Um die Verbindung zu einer anderen Datenbank zu trennen, ändern Sie einfach current_database() auf den Namen der Datenbank, von der Sie die Verbindung zu den Benutzern trennen möchten.

Sie möchten vielleicht REVOKE el CONNECT von den Nutzern der Datenbank, bevor Sie die Verbindung trennen. Andernfalls werden sich die Nutzer immer wieder neu verbinden und Sie werden nie die Möglichkeit haben, die DB zu löschen. Siehe dieser Kommentar und die Frage, mit der sie verbunden ist, Wie kann ich alle anderen Benutzer von der Datenbank trennen? .

Wenn Sie nur untätige Benutzer trennen wollen, siehe diese Frage .

3 Stimmen

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

79voto

Lukasz Szozda Punkte 137580

PostgreSQL 13 eingeführt FORCE opción.

DROP DATABASE

DROP DATABASE lässt eine Datenbank fallen ... Auch, wenn jemand anderes mit der Zieldatenbank verbunden ist, wird dieser Befehl fehlschlagen, es sei denn, Sie verwenden die FORCE Option, die weiter unten beschrieben wird.

FORCE

Versucht, alle bestehenden Verbindungen zur Zieldatenbank zu beenden. Es wird nicht beendet, wenn vorbereitete Transaktionen, aktive logische Replikations-Slots oder Abonnements in der Zieldatenbank vorhanden sind.

DROP DATABASE db_name WITH (FORCE);

0 Stimmen

Gibt es eine Lösung für Postgresql 11?

28voto

devdrc Punkte 1342

Kinderleicht.

Ich starte den Dienst in Ubuntu einfach neu, um die Verbindung zu den Clients zu trennen.

sudo service postgresql stop
sudo service postgresql start

psql
DROP DATABASE DB_NAME;

4 Stimmen

Das ist Overengineering. Drücken Sie einfach die Reset-Taste.

0 Stimmen

dropdb DB_NAME Sie müssen nicht in Postgres gehen.

0 Stimmen

@BicameralMind Sie müssen Folgendes verwenden dropdb mydb --force wenn es aktive Nutzer gibt.

27voto

a_horse_with_no_name Punkte 489934

Sie können alle Verbindungen vor dem Beenden der Datenbank mit dem Befehl pg_terminate_backend(int) Funktion.

Sie können alle laufenden Backends über die Systemansicht abrufen pg_stat_activity

Ich bin mir nicht ganz sicher, aber das Folgende würde wahrscheinlich alle Sitzungen beenden:

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

Natürlich dürfen Sie selbst nicht mit dieser Datenbank verbunden sein

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X