PostgreSQLデータベースへのアクティブな接続がある場合、PostgreSQLデータベースを削除するにはどうすればよいですか?


649

PostgreSQLデータベースを削除するスクリプトを作成する必要があります。多くの接続があるかもしれませんが、スクリプトはそれを無視する必要があります。

DROP DATABASE db_name開いている接続がある場合、標準クエリは機能しません。

どうすれば問題を解決できますか?


1
PostgreSQLのどのバージョンを使用していますか?
Kuberchaun

1
問題:データベースに接続されているセッションを強制終了する場合がありますが、セッションがすぐに再接続されるため、データベースを削除できません。あなたは、現在の接続を殺すし、計画どおりにデータベースをドロップすることができますので、新しい接続をロックアウトする方法幸いにもこの記事ショー: dba.stackexchange.com/questions/11893/...
マックス・マーフィー

1
私はdba.stackexchangeに比べてこの答えは非常に有用であることが判明dba.stackexchange.com/a/11895/163539簡潔まだ十分に説明- 。
hlongmore 2018年

回答:


1094

これはあなたのものを除いて既存の接続を落とします:

pg_stat_activitykillするpid値をクエリして取得し、SELECT pg_terminate_backend(pid int)それらに発行します。

PostgreSQL 9.2以降:

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB' -- ← change this to your DB
  AND pid <> pg_backend_pid();

PostgreSQL 9.1以前:

SELECT pg_terminate_backend(pg_stat_activity.procpid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB' -- ← change this to your DB
  AND procpid <> pg_backend_pid();

全員を切断したら、切断して、ドロップしようとしているデータベースではなく、別のデータベースからの接続からDROP DATABASEコマンドを発行する必要があります。

procpid列の名前が​​に変更されていることに注意してくださいpidこのメーリングリストのスレッドをご覧ください。


11
そしてもちろん、「TARGET_DB」への接続ではないdb接続からそれを行うようにしてください。そうしないと、「エラー」が発生します。「postgres」接続はうまく機能します。
Rob

3
実際には、クライアントを1つずつ切断します。クライアントがリストの真ん中にある場合は、クライアントも切断されます。その結果、一部の接続は存続します。したがって、正しい答えはCraig Ringerです(下記を参照)。SELECT pg_terminate_backend(pg_stat_activity.pid)FROM pg_stat_activity WHERE datname = current_database()AND pg_stat_activity.pid <> pg_backend_pid();
アンドリューセリバノフ2013

1
現在のトランザクションが終了した後で接続を切断し、問題のテーブルを削除するにはどうすればよいですか?
ポールコン、2015

5
私の場合、クライアントはすばやく再接続するので、私の場合、これを直前に置くと; drop database TARGET_DB;うまくいき、再試行が始まるまでにdbがなくなったことを確認できます。
Mat Schaffer

1
私もお金を払うでしょうdropdb --force
Torsten Bronger

125

PostgreSQL 9.2以降では、セッション以外のすべてを接続しているデータベースから切断するには:

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE datname = current_database()
  AND pid <> pg_backend_pid();

古いバージョンでも同じですが、に変更pidしてくださいprocpid。別のデータベースから切断するには、current_database()ユーザーを切断するデータベースの名前に変更します。

あなたはしたいことがあり、ユーザーを切断する前に、データベースのユーザーから右のそれ以外のユーザーは、ちょうど再接続し続けますと、あなたはDBをドロップするチャンスを得ることは決してないだろう。このコメントとそれに関連する質問を参照してください。他のすべてのユーザーをデータベースから切り離すにどうすればよいですかREVOKECONNECT

アイドル状態のユーザーを切断したいだけの場合は、この質問を参照してください。


3
SELECT pg_terminate_backend(pg_stat_activity.pid)FROM pg_stat_activity WHERE datname = current_database()AND pg_stat_activity.pid <> pg_backend_pid();
Andrew Selivanov 2013

26

pg_terminate_backend(int)関数を使用してデータベースを削除する前に、すべての接続を強制終了できます。

システムビューを使用して、実行中のすべてのバックエンドを取得できます pg_stat_activity

完全にはわかりませんが、次の場合はおそらくすべてのセッションが強制終了されます。

select pg_terminate_backend(procpid)
from pg_stat_activity
where datname = 'doomed_database'

もちろん、自分はそのデータベースに接続していない可能性があります


19

postgresqlのバージョンによっては、pg_stat_activityドロップされたユーザーからのアクティブな接続を除外するというバグに遭遇する可能性があります。これらの接続は、pgAdminIII内にも表示されません。

(ユーザーも作成する)自動テストを実行している場合、これはおそらくシナリオです。

この場合、次のようなクエリに戻す必要があります。

 SELECT pg_terminate_backend(procpid) 
 FROM pg_stat_get_activity(NULL::integer) 
 WHERE datid=(SELECT oid from pg_database where datname = 'your_database');

注:9.2以降では、に変更さprocpidpidます。


1
これは私が探していたものですが(9.2以降を想定)、pg_stat_activityへの参照を削除し、procpidをpidに変更する必要があります。
MDR、

2
このスニペットに変更procpidするとpid、9.3で動作します。
jb。

pg_stat_activityを削除しなくても?9.2でエラーが発生しました
MDR

OK。今私は理解しています、それはタイプミスでした。ありがとう!
jb。

2
9.3以降SELECT pg_terminate_backend(pid)FROM pg_stat_get_activity(NULL :: integer)WHERE datid =(SELECT oid from pg_database where datname = 'your_database');
Shawn Vader

17

postgres 9.2がprocpidではなく列pidを呼び出すようになったことに気づきました。

私はそれをシェルから呼び出す傾向があります:

#!/usr/bin/env bash
# kill all connections to the postgres server
if [ -n "$1" ] ; then
  where="where pg_stat_activity.datname = '$1'"
  echo "killing all connections to database '$1'"
else
  echo "killing all connections to database"
fi

cat <<-EOF | psql -U postgres -d postgres 
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
${where}
EOF

お役に立てば幸いです。SQLの@JustBobに感謝します。


15

Ubuntuでサービスを再起動して、接続しているクライアントを切断します。

sudo service postgresql stop
sudo service postgresql start

psql
DROP DATABASE DB_NAME;

10

Linuxコマンドプロンプトでは、最初にこのコマンドsudo /etc/init.d/postgresql restartを実行して、実行中のすべてのpostgresqlプロセスを停止します。

コマンドbgを入力して、 他のpostgresqlプロセスがまだ実行されているかどうかを確認します

次にdropdb dbnameを実行してデータベースを削除します

sudo /etc/init.d/postgresql restart
bg
dropdb dbname

これはLinuxコマンドプロンプトで私のために動作します


6
これは、多くのデータベースがあり、単一のDBの接続のみをドロップする場合は、良くありません。これはすべての接続を殺します。少し「そりハンマー」です。
ニック

2
@Nick trueですが、すべての接続を再起動して完全に停止していることを覚えておいてください
Maurice Elagu

10

PostgreSQL 9.2以降:

SELECT pg_terminate_backend(pid)FROM pg_stat_activity WHERE datname = 'YOUR_DATABASE_NAME_HERE'


それもアクティブな接続を終了しませんか?
ココワラ

8

これが私のハックです... = D

# Make sure no one can connect to this database except you!
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "UPDATE pg_database SET datallowconn=false WHERE datname='<DATABASE_NAME>';"

# Drop all existing connections except for yours!
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '<DATABASE_NAME>' AND pid <> pg_backend_pid();"

# Drop database! =D
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "DROP DATABASE <DATABASE_NAME>;"

新しい接続をブロックするコマンド(上記)を含めるため、およびコマンドでのすべての試行のため、この答えを出しました...

REVOKE CONNECT ON DATABASE <DATABASE_NAME> FROM PUBLIC, <USERS_ETC>;

...新しい接続をブロックするように機能しない!

@araqnid @GoatWalkerに感謝します!= D

https://stackoverflow.com/a/3185413/3223785


5

次のPostgreSQL 13ではFORCEオプションが導入されます。

ドロップデータベース

DROP DATABASEはデータベースを削除します...また、他の誰かがターゲットデータベースに接続している場合、以下で説明するFORCEオプションを使用しない限りこのコマンドは失敗します。

ターゲットデータベースへの既存の接続をすべて終了してみます。準備されたトランザクション、アクティブな論理レプリケーションスロット、またはサブスクリプションがターゲットデータベースに存在する場合は、終了しません。

DROP DATABASE db_name WITH (FORCE);

0

私の場合、アクティブな管理者接続を含むすべての接続をドロップするコマンドを実行する必要がありました

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE datname = current_database()

すべての接続が終了し、致命的な「エラー」メッセージが表示されました:

FATAL: terminating connection due to administrator command SQL state: 57P01

その後、データベースを削除することができました


0

pgAdmin4を使用してログインし、pgAdmin4以外のすべての接続を切断してから、データベースとプロパティを右クリックして名前を変更し、新しい名前を入力しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.