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.

22voto

jb. Punkte 21920

Abhängig von Ihrer Version von Postgresql können Sie auf einen Fehler stoßen, der die pg_stat_activity um aktive Verbindungen von gelöschten Benutzern auszulassen. Diese Verbindungen werden auch in pgAdminIII nicht angezeigt.

Wenn Sie automatische Tests durchführen (bei denen Sie auch Benutzer anlegen), könnte dies ein wahrscheinliches Szenario sein.

In diesem Fall müssen Sie auf Abfragen wie diese zurückgreifen:

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

HINWEIS: In 9.2+ müssen Sie die procpid zu pid .

1 Stimmen

Das ist es, wonach ich gesucht habe, aber für (vorausgesetzt 9.2 und höher) müssen Sie den Verweis auf pg_stat_activity entfernen und procpid in pid ändern.

2 Stimmen

Nach dem Wechsel procpid a pid dieses Snippet funktioniert unter 9.3.

0 Stimmen

Auch ohne Entfernen von pg_stat_activity? Ich bekam einen Fehler unter 9.2

17voto

kbrock Punkte 908

Ich habe festgestellt, dass Postgres 9.2 jetzt die Spalte pid statt procpid nennt.

Ich neige dazu, sie aus der Schale zu rufen:

#!/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

Ich hoffe, das ist hilfreich. Danke an @JustBob für die sql.

16voto

Marcelo C. Punkte 3644

PostgreSQL 9.2 und höher:

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

0 Stimmen

Wird dadurch nicht auch die aktive Verbindung unterbrochen?

11voto

Eduardo Lucio Punkte 1103

Hier ist mein 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>;"

Ich habe diese Antwort gegeben, weil ein Befehl (oben) zum Blockieren neuer Verbindungen enthalten ist und weil jeder Versuch mit dem Befehl ...

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

... funktioniert nicht, um neue Verbindungen zu blockieren!

Danke an @araqnid @GoatWalker! =D

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

8voto

Maurice Elagu Punkte 740

In der Linux-Eingabeaufforderung würde ich zunächst alle laufenden postgresql-Prozesse mit folgendem Befehl anhalten sudo /etc/init.d/postgresql neu starten

Geben Sie den Befehl bg um zu prüfen, ob andere postgresql-Prozesse noch laufen

dann gefolgt von dropdb dbname um die Datenbank zu löschen

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

Dies funktioniert bei mir in der Linux-Eingabeaufforderung

6 Stimmen

Dies ist nicht gut, wenn Sie viele Datenbanken haben und nur Verbindungen für eine einzige DB löschen wollen. Dies würde alle Verbindungen beenden. Es ist ein bisschen wie ein Vorschlaghammer.

2 Stimmen

@Nick Stimmt, aber denken Sie daran, dass wir alle Verbindungen neu starten und sie vollständig stoppen.

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