How to drop a PostgreSQL database if there are active connections to it?
我需要编写一个脚本来删除PostgreSQL数据库。可能有很多连接到它,但是脚本应该忽略这一点。
当存在打开的连接时,标准的
我怎样才能解决这个问题?
这将删除除您的以外的现有连接:
查询
PostgreSQL 9.2及以上版本:
1 2 3 4 | 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及以下:
1 2 3 4 | 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命令,也就是说,不是您要删除的数据库。
注意将
在PostgreSQL 9.2及更高版本中,要断开除会话之外的所有与所连接数据库的连接,请执行以下操作:
1 2 3 4 | SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE datname = current_database() AND pid <> pg_backend_pid(); |
在旧版本中是一样的,只需将
在断开用户连接之前,您可能希望从数据库的用户那里获得
如果只想断开空闲用户的连接,请参见此问题。
在使用
您可以使用系统视图
我不完全确定,但以下可能会扼杀所有会话:
1 2 3 | SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE datname = 'doomed_database' |
当然,您可能无法连接到该数据库
我注意到Postgres9.2现在调用的是列pid而不是procpid。
我倾向于从外壳来称呼它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/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 |
希望有帮助。感谢@justbob提供的SQL。
根据您的PostgreSQL版本的不同,您可能会遇到一个bug,这使得
如果您正在进行自动测试(其中还创建了用户),这可能是一个可能的场景。
在这种情况下,您需要恢复到如下查询:
1 2 3 | 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+中,您将把
在Linux命令提示符中,我将首先通过绑定此命令停止所有正在运行的PostgreSQL进程。sudo/etc/init.d/postgresql重启
键入命令bg检查其他PostgreSQL进程是否仍在运行
然后跟随dropdb dbname删除数据库
1 2 3 | sudo /etc/init.d/postgresql restart bg dropdb dbname |
这对我在Linux命令提示符下有效
我只是重新启动Ubuntu中的服务来断开连接的客户机。
1 2 3 4 5 | sudo service postgresql stop sudo service postgresql START psql DROP DATABASE DB_NAME; |
PostgreSQL 9.2及以上版本:
这是我的黑客…= D
1 2 3 4 5 6 7 8 | # 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>;" |
我之所以给出这个答案,是因为包含了一个命令(在上面)来阻止新的连接,并且因为任何使用该命令的尝试…
1 | REVOKE CONNECT ON DATABASE <DATABASE_NAME> FROM PUBLIC, <USERS_ETC>; |
…不要阻止新连接!
感谢@araqnid@goatwalker!= D
https://stackoverflow.com/a/3185413/3223785
在我的例子中,我必须执行一个命令来删除所有连接,包括我的活动管理员连接。
1 2 3 | SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE datname = current_database() |
它终止了所有连接并向我显示致命的"错误"消息:
之后就可以删除数据库了