Force drop db, podczas gdy inne mogą być podłączone
103
Muszę usunąć bazę danych z klastra PostgreSQL DB. Jak mogę to zrobić, nawet jeśli istnieją aktywne połączenia? Potrzebuję coś w rodzaju -forceflagi, która porzuci wszystkie połączenia, a następnie DB.
Jak mogę to zaimplementować?
dropdbObecnie używam , ale inne narzędzia są możliwe.
W PostgreSQL * nie można upuścić bazy danych, gdy klienci są z nią połączeni.
Przynajmniej nie z dropdbnarzędziem - które jest tylko prostym otokiem wokół DROP DATABASEzapytania serwera.
Całkiem solidne obejście:
Połącz się z serwerem jako administrator , za pomocą psqllub 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_activityWHERE 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.
DROPDATABASE 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.
Więc nie wiem, co zrobiłem źle, ale teraz nie mogę nawet połączyć się z bazą danych, na którą celowałem! Nie mogę też tego upuścić, ponieważ napisano: „Nie można usunąć bazy danych konserwacji”
Matt Skeldon
@MattSkeldon, nie mam pojęcia, co oznacza ta wiadomość. W waniliowym PostgreSQL możesz upuścić dowolną bazę danych oprócz szablonu0 i szablonu1. Może używasz wersji niewolnej / komercyjnej? Może to problem klienta, a nie serwera? Próbowałeś psql?
filiprem
Niestety pochodzę z języka SQL, ponieważ używa się PGSQL ze względu na status niekomercyjny / wolny.
Matt Skeldon
To nie działa dla mnie w przypadku długotrwałych sesji zombie. pg_terminate_backend () nie zabija tych sesji, więc wciąż trochę utknąłem w tym, co robić: jestem su Postgres, ale nie mam dostępu do serwera, na którym on działa.
Alexander
6
Jest na to sposób za pomocą narzędzi powłoki dropdbi pg_ctl(lub pg_ctlclusterw Debianie i pochodnych). Ale metoda @ filiprem jest lepsza z kilku powodów:
Odłącza tylko użytkowników od danej bazy danych.
Nie trzeba restartować całego klastra.
Zapobiega natychmiastowemu ponownemu podłączeniu, prawdopodobnie psując dropdbpolecenie.
Cytuję man pg_ctlcluster:
Z --forceopcją 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.
Nie tylko jest to mniej niż idealne, ponieważ uruchamia pełną instancję postgres, ale nie gwarantuje, że zadziała. Klient może połączyć się między ponownym uruchomieniem serwera a próbą ponownego uruchomienia dropdb. Powyższa odpowiedź @filiprem wyłącza wszystkie połączenia z bazą danych przed rozłączeniem i podtrzymuje działanie innych baz danych.
Jim Mitchener
6
Korzystanie z odpowiedzi @ filiprem w mojej sprawie i uproszczenie jej:
-- Connecting to the current user localhost's postgres instance
psql-- Making sure the database existsSELECT*from pg_database where datname ='my_database_name'-- Disallow new connectionsUPDATE pg_database SET datallowconn ='false'WHERE datname ='my_database_name';ALTERDATABASE my_database_name CONNECTION LIMIT 1;-- Terminate existing connectionsSELECT pg_terminate_backend(pid)FROM pg_stat_activity WHERE datname ='my_database_name';-- Drop databaseDROPDATABASE 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.
Jest na to sposób za pomocą narzędzi powłoki
dropdb
ipg_ctl
(lubpg_ctlcluster
w Debianie i pochodnych). Ale metoda @ filiprem jest lepsza z kilku powodów:dropdb
polecenie.Cytuję
man pg_ctlcluster
:lub
lub
natychmiast następuje:
Prawdopodobnie w skrypcie do natychmiastowej sukcesji.
źródło
Korzystanie z odpowiedzi @ filiprem w mojej sprawie i uproszczenie jej:
źródło
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.
źródło