回答:
PostgreSQL *では、クライアントが接続している間はデータベースを削除できません。
少なくとも、dropdb
ユーティリティを使用しない場合- DROP DATABASE
サーバークエリの単なるラッパーです。
非常に堅牢な回避策は次のとおりです。
またはその他のクライアントを使用して、スーパーユーザーとしてサーバーに接続しますpsql
。削除するデータベースを使用しないでください。
psql -h localhost postgres postgres
プレーンデータベースクライアントを使用すると、3つの簡単な手順でデータベースを強制的にドロップできます。
このデータベースに誰も接続できないことを確認してください。次の方法のいずれかを使用できます(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; */
を使用して、このデータベースに接続されているすべてのクライアントを強制的に切断します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'; */
データベースを削除します。
DROP DATABASE mydb;
ステップ1では、1番目の方法にはスーパーユーザー特権が、2番目の方法にはデータベース所有者特権が必要です。ステップ2にはスーパーユーザー特権が必要です。ステップ3には、データベース所有者特権が必要です。
* これは、バージョン11までのPostgreSQLのすべてのバージョンに適用されます。
そこでシェルユーティリティでこれを行う方法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
おそらくすぐに継承するためのスクリプトで。
私のケースで@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
データベースを選択せずに接続すると、デフォルトで作成するように要求された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;