如果有一个活动的连接,如何删除PostgreSQL数据库?

Rom*_*nko 605 postgresql

我需要编写一个删除PostgreSQL数据库的脚本.它可能有很多连接,但脚本应该忽略它.

DROP DATABASE db_name当存在打开的连接时,标准查询不起作用.

我该如何解决这个问题?

Kub*_*aun 1039

这将删除除您的连接之外的现有连接:

查询pg_stat_activity并获取要杀死的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();
Run Code Online (Sandbox Code Playgroud)

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();
Run Code Online (Sandbox Code Playgroud)

一旦断开所有人的连接,您将不得不断开连接并从另一个数据库(即您尝试删除的数据库)的连接发出DROP DATABASE命令.

请注意将procpid列重命名为pid.查看此邮件列表主题.

  • 当然,请务必从不与"TARGET_DB"连接的数据库连接执行此操作,否则会出现"错误".'postgres'连接效果很好. (8认同)
  • 在我的情况下,客户会快速重新连接,所以在`之前放置它; drop database TARGET_DB;`在我的情况下运行良好,以确保在事情开始重试时数据库已经消失. (5认同)
  • @TorstenBronger 授予!https://github.com/postgres/postgres/commit/1379fd537f9fc7941c8acff8c879ce3636dbdb77 (4认同)
  • 我什至愿意花钱购买“dropdb --force”。 (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(); (2认同)

Cra*_*ger 120

在PostgreSQL 9.2及更高版本中,要从连接到的数据库中断开除会话之外的所有内容:

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE datname = current_database()
  AND pid <> pg_backend_pid();
Run Code Online (Sandbox Code Playgroud)

在旧版本中它是相同的,只需更改pidprocpid.要断开与其他数据库的连接,只需更改current_database()为要断开用户连接的数据库的名称.

在断开用户连接之前,您可能希望从数据库用户那里REVOKE获得CONNECT权利,否则用户将继续重新连接,您将永远不会有机会丢弃数据库.请参阅此注释及其相关问题,如何从数据库中分离所有其他用户.

如果您只想断开空闲用户,请参阅此问题.

  • SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE datname = current_database() AND pg_stat_activity.pid &lt;&gt; pg_backend_pid(); (2认同)

Luk*_*zda 30

PostgreSQL 13 引入了FORCE选项。

删除数据库

DROP DATABASE删除数据库...此外,如果其他任何人连接到目标数据库,除非您使用下面描述的FORCE选项,否则此命令将失败。

力量

尝试终止与目标数据库的所有现有连接。如果目标数据库中存在准备好的事务、活动的逻辑复制槽或订阅,它不会终止。

DROP DATABASE db_name WITH (FORCE);
Run Code Online (Sandbox Code Playgroud)


a_h*_*ame 26

您可以在使用该pg_terminate_backend(int)函数删除数据库之前终止所有连接.

您可以使用系统视图获取所有正在运行的后端 pg_stat_activity

我不完全确定,但以下可能会杀死所有会话:

select pg_terminate_backend(procpid)
from pg_stat_activity
where datname = 'doomed_database'
Run Code Online (Sandbox Code Playgroud)

当然,您可能无法将自己连接到该数据库


jb.*_*jb. 18

根据您的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');
Run Code Online (Sandbox Code Playgroud)

注:在9.2+你必须改变procpidpid.

  • 将``procpid``改为``pid``后,这个代码片段在9.3上工作. (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'); (2认同)

kbr*_*ock 17

我注意到postgres 9.2现在调用列pid而不是procpid.

我倾向于从shell中调用它:

#!/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
Run Code Online (Sandbox Code Playgroud)

希望有所帮助.感谢@JustBob为sql.


dev*_*drc 14

我只是在Ubuntu中重新启动服务以断开连接的客户端.

sudo service postgresql stop
sudo service postgresql start

psql
DROP DATABASE DB_NAME;
Run Code Online (Sandbox Code Playgroud)

  • 这是过度设计。只需按下重置按钮即可。 (5认同)

Mau*_*agu 10

在Linux命令提示符中,我将首先通过绑定此命令来停止所有正在运行的postgresql进程 sudo /etc/init.d/postgresql restart

键入命令 bg以检查其他postgresql进程是否仍在运行

然后是dropdb dbname以删除数据库

sudo /etc/init.d/postgresql restart
bg
dropdb dbname
Run Code Online (Sandbox Code Playgroud)

这在linux命令提示符下适用于我

  • 如果您有许多数据库并且只想删除单个数据库的连接,那么这并不好.这会杀死所有连接.这有点"雪橇锤". (6认同)
  • @Nick是的,但是请记住我们正在重新启动所有连接并完全停止了它们 (2认同)

小智 9

PostgreSQL 9.2及以上版本:

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


Edu*_*cio 7

这是我的hack ... = 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>;"
Run Code Online (Sandbox Code Playgroud)

我给出这个答案,是因为(上面)包含了一个阻止新连接的命令,并且因为对该命令的任何尝试 ...

REVOKE CONNECT ON DATABASE <DATABASE_NAME> FROM PUBLIC, <USERS_ETC>;
Run Code Online (Sandbox Code Playgroud)

...不能阻止新的连接!

感谢@araqnid @GoatWalker!= D

/sf/answers/222978941/