Jak zrzucić bazę danych PostgreSQL, jeśli są do niej aktywne połączenia?

Muszę napisać skrypt, który upuści bazę danych PostgreSQL. Może być z nim wiele połączeń, ale skrypt powinien to zignorować.

Standardowe zapytanie DROP DATABASE db_name nie działa, gdy istnieją otwarte połączenia.

Jak mogę rozwiązać problem?
 514
Author: Kuberchaun, 2011-03-23

10 answers

To usunie istniejące połączenia z wyjątkiem twojego:

Zapytanie pg_stat_activity i pobierz wartości pid, które chcesz zabić, a następnie wydaj im SELECT pg_terminate_backend(pid int).

PostgreSQL 9.2 i wyżej:

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 i poniżej:

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

Po odłączeniu wszystkich będziesz musiał odłączyć i wydać polecenie DROP DATABASE z połączenia z innej bazy danych aka nie ten, który próbujesz upuścić.

Zwróć uwagę na zmianę nazwy kolumny procpid na pid. Zobacz ten wątek listy dyskusyjnej .

 890
Author: Kuberchaun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-08 03:43:52

W PostgreSQL 9.2 i nowszych, aby odłączyć wszystko poza sesją od bazy danych, do której jesteś podłączony:

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

W starszych wersjach jest to samo, wystarczy zmienić pid na procpid. Aby odłączyć się od innej bazy danych, po prostu zmień current_database() na nazwę bazy danych, z której chcesz odłączyć użytkowników.

Możesz chcieć REVOKE CONNECT bezpośrednio od użytkowników bazy danych przed odłączeniem użytkowników, w przeciwnym razie użytkownicy będą po prostu ponownie się łączyć i nigdy nie otrzymasz szansa na zrzucenie DB. Zobacz ten komentarz i pytanie, z którym jest związany, Jak odłączyć wszystkich innych użytkowników od bazy danych .

Jeśli chcesz po prostu odłączyć bezczynnych użytkowników, zobacz to pytanie .

 98
Author: Craig Ringer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:44

Można zabić wszystkie połączenia przed upuszczeniem bazy danych za pomocą funkcji pg_terminate_backend(int).

Możesz pobrać wszystkie uruchomione backendy używając widoku systemowego pg_stat_activity

Nie jestem do końca pewien, ale poniższe prawdopodobnie zabiłoby wszystkie sesje:

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

Oczywiście możesz nie być podłączony do tej bazy danych

 25
Author: a_horse_with_no_name,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-23 16:28:27

Zauważyłem, że postgres 9.2 nazywa teraz kolumnę pid, a nie procpid.

Zwykle nazywam to z muszli:

#!/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
Mam nadzieję, że to pomoże. Dzięki @JustBob za sql.
 16
Author: kbrock,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-23 03:35:17

W zależności od wersji postgresql może pojawić się błąd, który sprawia, że pg_stat_activity pomija aktywne połączenia od usuniętych użytkowników. Połączenia te również nie są pokazane wewnątrz pgAdminIII.

Jeśli wykonujesz automatyczne testy (w których również tworzysz użytkowników), może to być prawdopodobny scenariusz.

W tym przypadku musisz powrócić do zapytań typu:

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

Uwaga: w 9.2+ będziesz miał zmianę procpid na pid.

 12
Author: jb.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-11 09:53:25

W wierszu polecenia Linuksa, najpierw zatrzymałbym wszystkie uruchomione procesy postgresql, wiążąc to polecenie sudo /etc / init.d / postgresql restart

Wpisz polecenie bg aby sprawdzić, czy inne procesy postgresql nadal działają

Następnie dropdb dbname aby upuścić bazę danych

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

To działa dla mnie w Linuksie wiersz polecenia

 7
Author: Maurice Elagu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-29 07:55:10

Po prostu restartuję usługę w Ubuntu, aby odłączyć podłączonych klientów.

sudo service postgresql stop
sudo service postgresql start

psql
DROP DATABASE DB_NAME;
 6
Author: devdrc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-13 20:03:12

PostgreSQL 9.2 i wyżej:

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

 4
Author: Marcelo C.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-22 17:39:23

Oto mój haczyk... =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>;"

Umieściłem tę odpowiedź, ponieważ zawiera polecenie (powyżej) blokujące nowe połączenia i Ponieważ każda próba użycia polecenia ...

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

... nie działa blokowanie nowych połączeń!

Dzięki @ araqnid @ GoatWalker ! =D

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

 3
Author: Eduardo Lucio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-20 13:23:22

W moim przypadku musiałem wykonać polecenie, aby usunąć wszystkie połączenia, w tym moje aktywne połączenie administratora

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

Który przerwał wszystkie połączenia i pokazał mi fatalny komunikat "Błąd":

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

Po tym można było porzucić bazę danych

 0
Author: Chtiwi Malek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-02 10:55:14