Сила скидання db, хоча інші можуть бути підключені


103

Мені потрібно видалити базу даних із кластеру DB PostgreSQL. Як я можу це зробити, навіть якщо є активні з'єднання? Мені потрібен такий собі -forceпрапор, який перестане всі з'єднання, а потім БД.

Як я можу це реалізувати?

dropdbЗараз я використовую , але інші інструменти можливі.

Відповіді:


154

У PostgreSQL * ви не можете скинути базу даних, поки клієнти підключені до неї.

Принаймні, не з dropdbутилітою - яка є лише простою обгорткою навколо DROP DATABASEзапиту сервера.

Досить надійний спосіб вирішення:

Підключіться до свого сервера як суперпользователь , користувач psqlабо інший клієнт. Як НЕ використовувати базу даних , яку ви хочете відмовитися.

psql -h localhost postgres postgres

Тепер, використовуючи звичайний клієнт бази даних, ви можете змусити випадати базу даних за допомогою трьох простих кроків:

  1. Переконайтесь, що ніхто не може підключитися до цієї бази даних. Можна скористатися одним із наступних методів (другий здається більш безпечним, але не перешкоджає з'єднанню суперпользователей).

    /* 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; */
  2. Примусове відключення всіх клієнтів, підключених до цієї бази даних, за допомогою 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'; */
  3. Відкиньте базу даних.

    DROP DATABASE mydb;

Крок 1 вимагає привілеїв суперпользователя для 1-го методу, а права власника бази даних - для другого. Крок 2 вимагає привілеїв суперпользователя . Крок 3 вимагає права власника бази даних .


* Це стосується всіх версій PostgreSQL, аж до версії 11.



Тому я не знаю, що я зробив не так, але тепер я навіть не можу підключитися до націленої на мене бази даних! Я також не можу скинути його, як там написано: "Базу технічного обслуговування не можна скинути"
Метт Скелдон,

@MattSkeldon, не маю уявлення, що означає це повідомлення. У vanilla PostgreSQL ви можете залишити будь-яку базу даних, крім template0 та template1. Можливо, ви використовуєте якусь невільну / комерційну версію? Можливо, це проблема клієнта, а не сервер? Ви спробували psql?
filiprem

На жаль, я походжу з фонового режиму SQL, оскільки PGSQL використовується завдяки некомерційному / вільному статусу.
Метт Скелдон

Це не працює для мене, коли є тривалі сеанси зомбі. pg_terminate_backend () не вбиває ці сеанси, тому я все ще трохи застряг у тому, що робити: я Postgres su, але у мене немає доступу до сервера, на якому він працює.
Олександр

6

Там є спосіб зробити це з допомогою утиліти оболонки dropdbі pg_ctl(або pg_ctlclusterв Debian і дериватів). Але метод @ filiprem є кращим з кількох причин:

  • Він лише відключає користувачів від відповідної бази даних.
  • Для цього не потрібно перезапускати весь кластер.
  • Це запобігає негайному повторному підключенню, можливо, зіпсує dropdbкоманду.

Цитую man pg_ctlcluster:

За допомогою --forceопції використовується режим "швидкого", який відкидає всі активні транзакції, негайно відключає клієнтів і таким чином вимикається чисто. Якщо це не допоможе, спробу відключення спробують знову в режимі "негайного", що може залишити кластер у непослідовному стані і, таким чином, призведе до запуску відновлення при наступному запуску. Якщо це все-таки не допомагає, процес поштового зв’язку вбивається. Виходить з 0 на успіх, з 2, якщо сервер не працює, і з 1 в інших умовах відмови. Цей режим слід використовувати лише тоді, коли машина збирається вимкнути.

pg_ctlcluster 9.1 main restart --force

або

pg_ctl restart -D datadir -m fast

або

pg_ctl restart -D datadir -m immediate

одразу слідує:

dropdb mydb

Можливо, в сценарії для негайної спадкоємності.


4
Це не тільки ідеально, оскільки він запускає повний екземпляр постгресі, але це не гарантовано працює. Клієнт може підключитися між тим, як перезапустити сервер, і спробувати запустити dropdb знову. Відповідь @filiprem вище відключає всі підключення до бази даних перед відключенням і підтримуватиме інші бази даних.
Джим Мітченер

6

Використання @ filiprem відповіді в моєму випадку та спрощення її:

-- 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

0

Якщо у вас є щось на зразок RDS, коли з'єднання без обраної бази даних вводять вас у БД, яку ви просили створити за замовчуванням, ви можете виконати цей варіант, щоб обійти себе останнім відкритим з'єднанням.

 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;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.