Odpowiedzi:
W PostgreSQL * nie można upuścić bazy danych, gdy klienci są z nią połączeni.
Przynajmniej nie z dropdb
narzędziem - które jest tylko prostym otokiem wokół DROP DATABASE
zapytania serwera.
Całkiem solidne obejście:
Połącz się z serwerem jako administrator , za pomocą psql
lub innego klienta. Czy nie korzystać z bazy danych, którą chcesz upuścić.
psql -h localhost postgres postgres
Teraz za pomocą zwykłego klienta bazy danych możesz wymusić usunięcie bazy danych, wykonując trzy proste kroki:
Upewnij się, że nikt nie może połączyć się z tą bazą danych. Możesz użyć jednej z następujących metod (druga wydaje się bezpieczniejsza, ale nie uniemożliwia połączeń z superużytkownikami).
/* Method 1: update system catalog */
UPDATE pg_database SET datallowconn = 'false' WHERE datname = 'mydb';
/* Method 2: use ALTER DATABASE. Superusers still can connect!
ALTER DATABASE mydb CONNECTION LIMIT 0; */
Wymuś rozłączenie wszystkich klientów podłączonych do tej bazy danych, używając pg_terminate_backend
.
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'mydb';
/* For old versions of PostgreSQL (up to 9.1), change pid to procpid:
SELECT pg_terminate_backend(procpid)
FROM pg_stat_activity
WHERE datname = 'mydb'; */
Upuść bazę danych.
DROP DATABASE mydb;
Krok 1 wymaga uprawnień administratora w przypadku pierwszej metody oraz uprawnień właściciela bazy danych w przypadku drugiej metody. Krok 2 wymaga uprawnień administratora . Krok 3 wymaga uprawnień właściciela bazy danych .
* Dotyczy to wszystkich wersji PostgreSQL, aż do wersji 11.
Jest na to sposób za pomocą narzędzi powłoki dropdb
i pg_ctl
(lub pg_ctlcluster
w Debianie i pochodnych). Ale metoda @ filiprem jest lepsza z kilku powodów:
dropdb
polecenie.Cytuję man pg_ctlcluster
:
Z
--force
opcją używany jest tryb „szybki”, który wycofuje wszystkie aktywne transakcje, natychmiast rozłącza klientów, a tym samym czyści się automatycznie. Jeśli to nie zadziała, nastąpi próba zamknięcia systemu w trybie „natychmiastowym”, co może pozostawić klaster w niespójnym stanie, a tym samym doprowadzić do uruchomienia odzyskiwania przy następnym uruchomieniu. Jeśli to nadal nie pomaga, proces postmastera zostaje zabity. Wychodzi z 0 w przypadku powodzenia, z 2, jeśli serwer nie działa, i z 1 w innych warunkach awarii. Z tego trybu należy korzystać tylko wtedy, gdy urządzenie ma zostać wyłączone.
pg_ctlcluster 9.1 main restart --force
lub
pg_ctl restart -D datadir -m fast
lub
pg_ctl restart -D datadir -m immediate
natychmiast następuje:
dropdb mydb
Prawdopodobnie w skrypcie do natychmiastowej sukcesji.
Korzystanie z odpowiedzi @ filiprem w mojej sprawie i uproszczenie jej:
-- Connecting to the current user localhost's postgres instance
psql
-- Making sure the database exists
SELECT * from pg_database where datname = 'my_database_name'
-- Disallow new connections
UPDATE pg_database SET datallowconn = 'false' WHERE datname = 'my_database_name';
ALTER DATABASE my_database_name CONNECTION LIMIT 1;
-- Terminate existing connections
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'my_database_name';
-- Drop database
DROP DATABASE my_database_name
Jeśli korzystasz z czegoś takiego jak RDS, w którym połączenia bez wybranej bazy danych wprowadzają Cię do DB, o którego utworzenie poprosiłeś, możesz zrobić ten wariant, aby obejść się jako ostatnie otwarte połączenie.
DROP DATABASE IF EXISTS temporary_db_that_shouldnt_exist;
CREATE DATABASE temporary_db_that_shouldnt_exist with OWNER your_user;
\connect temporary_db_that_shouldnt_exist
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'the_db_you_want_removed';
DROP DATABASE IF EXISTS the_db_you_want_removed;
--
-- Name: the_db_you_want_removed; Type: DATABASE; Schema: -; Owner: your_user
--
CREATE DATABASE savings_champion WITH TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8';
ALTER DATABASE the_db_you_want_removed OWNER TO your_user;
\connect the_db_you_want_removed
DROP DATABASE IF EXISTS temporary_db_that_shouldnt_exist;