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


103

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

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

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

回答:


154

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

少なくとも、dropdbユーティリティを使用しない場合- DROP DATABASEサーバークエリの単なるラッパーです。

非常に堅牢な回避策は次のとおりです。

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

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番目の方法にはスーパーユーザー特権が、2番目の方法にはデータベース所有者特権が必要です。ステップ2にはスーパーユーザー特権が必要です。ステップ3には、データベース所有者特権が必要です。


* これは、バージョン11までのPostgreSQLのすべてのバージョンに適用されます。



だから私は間違ったことを知りませんが、今ではターゲットとするデータベースに接続することさえできません!それは「保守データベースをドロップすることができません」と言うようにも私はそれをドロップすることができます
マット・Skeldon

@MattSkeldon、このメッセージの意味がわかりません。通常のPostgreSQLでは、template0とtemplate1以外のデータベースを削除できます。たぶんあなたはいくつかの非フリー/商用バージョンを使用していますか?たぶんそれはサーバーの問題ではなくクライアントの問題ですか?psqlを試しましたか?
filiprem

残念ながら、私はSQLのバックグラウンドから来ました。PGSQLの使用は、非商用/無料のステータスのために使用されています。
マット

これは、長時間実行されるゾンビセッションがある場合は機能しません。pg_terminate_backend()はそれらのセッションを強制終了しません。そのため、私はまだ何をすべきかについて少し立ち往生しています。私はPostgres suですが、実行中のサーバーにアクセスできません。
アレクサンダー

6

そこシェルユーティリティでこれを行う方法dropdbpg_ctl(またはpg_ctlclusterDebianと誘導体では)。しかし、@ 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
これは完全なpostgresインスタンスをキックするので理想的ではないだけでなく、動作することも保証されていません。サーバーを再起動してからdropdbを再度実行しようとする間に、クライアントが接続する可能性があります。上記の@filipremの回答は、切断する前にデータベースへのすべての接続を無効にし、他のデータベースを維持します。
ジムミッテナー14年

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

データベースを選択せず​​に接続すると、デフォルトで作成するように要求された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;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.