web-dev-qa-db-ja.com

他の人が接続されている可能性がある間、データベースを強制的に削除

PostgreSQL DBクラスターからデータベースを削除する必要があります。アクティブな接続がある場合でもどうすればよいですか? -forceフラグが必要です。これにより、すべての接続がドロップされ、次にDBがドロップされます。

どうすれば実装できますか?

現在dropdbを使用していますが、他のツールも使用できます。

126
Alex

PostgreSQL内*、クライアントが接続している間はデータベースを削除できません。

少なくとも、 dropdb ユーティリティでは使用できません。これは DROP DATABASE サーバークエリの単なるラッパーです。

かなり堅牢な回避策は次のとおりです。

psqlまたは他のクライアントを使用して、superuserとしてサーバーに接続します。削除するデータベースを使用するしない

psql -h localhost postgres postgres

プレーンデータベースクライアントを使用すると、3つの簡単な手順でデータベースを強制的に削除できます。

  1. 誰もこのデータベースに接続できないことを確認してください。次のいずれかの方法を使用できます(2番目の方法はより安全に見えますが、スーパーユーザーからの接続を妨げません)。

    /* 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番目のメソッドのsuperuser特権、およびデータベース所有者特権が必要です2つ目のために。ステップ2にはsuperuser特権が必要です。ステップ3にはデータベース所有者特権が必要です。


これは、バージョン12までのPostgreSQLのすべてのバージョンに適用されます。バージョン13にはDROP DATABASE mydb FORCEがあります。


178
filiprem

私のケースで@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
9
Dorian

シェルユーティリティdropdbpg_ctl(またはDebianとその派生物ではpg_ctlcluster)でこれを行う方法がです。しかし、@ filipremの方法 は、いくつかの理由で優れています

  • 問題のデータベースからユーザーを切断するだけです。
  • クラスタ全体を再起動する必要はありません。
  • 即時の再接続を防ぎ、dropdbコマンドを無効にする可能性があります。

引用するman pg_ctlcluster

--forceオプションを使用すると、すべてのアクティブなトランザクションをロールバックし、クライアントをすぐに切断して、完全にシャットダウンする「高速」モードが使用されます。それが機能しない場合は、「即時」モードでシャットダウンが再試行されます。これにより、クラスターが不整合な状態のままになり、次回の起動時にリカバリーが実行される可能性があります。それでも解決しない場合は、postmasterプロセスが強制終了されます。成功した場合は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

おそらく、すぐに引き継ぐために台本の中で.

7

データベースを選択せず​​に接続すると、デフォルトで作成するように要求されたDBに入る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;
0
Jharwood