2011-03-23 70 views
461

我需要编写一个脚本来删除PostgreSQL数据库。可能有很多连接,但脚本应该忽略它。如何删除PostgreSQL数据库,如果有活动的连接呢?

当打开连接时,标准DROP DATABASE db_name查询不起作用。

我该如何解决问题?

+0

你在什么版本的PostgreSQL上? – Kuberchaun 2011-03-23 17:16:47

+0

我使用PostgreSQL 8.4 – 2011-03-23 18:06:31

+0

问题:虽然您可能会终止连接到数据库的会话,但它们可能会很快重新连接,以至于仍无法删除数据库。令人高兴的是,这篇文章展示了如何锁定新的连接,这样你就可以终止当前连接并按照计划删除数据库:http://dba.stackexchange.com/questions/11893/force-drop-db-while-others -Yy-be-connected – 2016-04-11 10:56:24

回答

820

这将降低现有的连接,除了你:

查询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' 
    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' 
    AND procpid <> pg_backend_pid(); 

一旦断开每个人你必须断开和连接发出DROP DATABASE命令从另一个数据库,也就是你不想放弃的那个数据库。

请注意将procpid列重命名为pid。见this mailing list thread

+2

从8.4开始工作... – Daniel 2011-03-23 16:49:11

+5

当然,一定要从不连接到'TARGET_DB'的数据库连接执行该操作,否则会得到'错误'。 'postgres'连接运行良好。 – Rob 2011-07-26 16:00:26

+0

工程很好,只需要记住你不能连接到这个数据库!在pgAdmin的数据库中使用Disconnect。 – Konrad 2013-06-17 08:35:51

23

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

您可以使用系统视图pg_stat_activity

我不能完全肯定让所有正在运行的后端,但下面可能会杀死所有会话:

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

当然,你可能无法连接自己到那个数据库

15

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

我倾向于从外壳调用它:

#!/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。

86

在PostgreSQL 9.2及以上,断开一切除了你以外,连接到数据库会话:

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

在旧版本上是一样的,只是改变pidprocpid。要断开与其他数据库的连接,只需将current_database()更改为要断开用户连接的数据库的名称。

在断开用户连接之前,您可能希望REVOKECONNECT权限来自数据库的用户,否则用户将继续重新连接,并且永远不会有机会丢弃数据库。请参阅this comment及其关联的问题How do I detach all other users from the database

如果您只想断开闲置用户的连接,请参阅this question

+2

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-09-10 09:14:15

12

根据您的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

+0

这是我正在寻找,但(假设9.2及以上),你必须删除对pg_stat_activity的引用,并将procpid更改为pid。 – MDR 2013-12-08 21:07:03

+2

把''procpid''改成''pid''后,这个片段在9.3上工作。 – 2013-12-09 22:26:40

+0

即使不删除pg_stat_activity?我遇到9.2 – MDR 2013-12-10 23:49:29

6

在Linux命令提示符下,我会先停止正在通过把这个命令 须藤运行的所有PostgreSQL处理/etc/init.d/postgresql的重新启动

类型命令 BG检查其他PostgreSQL的进程仍在运行

再接着DROPDB DBNAME删除数据库

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

这对我的作品在Linux命令提示符

+3

如果您有许多数据库并且只想删除单个数据库的连接,那么这样做不好。这会杀死所有连接。这有点“大锤-y”。 – Nick 2016-02-12 15:34:19

+0

@Nick true,但请记住我们正在重新启动所有连接并完全停止它们 – 2016-02-15 09:24:45

+0

为我工作!谢谢你的简单解决方案! – rikkitikkitumbo 2016-12-07 07:48:57

3

的PostgreSQL 9.2及以上版本:

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

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

之后,它是能够丢弃数据库

2

这里是我的黑客... = 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

2

我只需重新启动在Ubuntu的服务断开连接的客户端。

sudo service postgresql stop 
sudo service postgresql start 

psql 
DROP DATABASE DB_NAME;