Postgresql -不能删除数据库,因为一些自动连接到DB

每当我尝试删除数据库时,我得到:

ERROR:  database "pilot" is being accessed by other users
DETAIL:  There is 1 other session using the database.

当我使用:

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB';

我终止了从该数据库的连接,但如果我试图在此之后删除数据库,有人以某种方式自动连接到该数据库并给出此错误。那是什么? 除了我,没有人使用这个数据库

255438 次浏览

只需检查连接是什么,它来自哪里。你可以看到这些:

SELECT * FROM pg_stat_activity WHERE datname = 'TARGET_DB';

也许这是你们之间的联系?

您可以阻止未来的连接:

REVOKE CONNECT ON DATABASE thedb FROM public;

(可能还有其他用户/角色;参见psql中的\l+)

然后你可以终止所有到这个db的连接,除了你自己的:

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

在旧版本中,pid被称为procpid,所以你必须处理这个问题。

既然你已经撤销了CONNECT权限,无论试图自动连接的是什么,都应该不再能够这样做。

现在可以删除DB了。

如果您使用超级用户连接进行正常操作,这将不起作用,但如果您正在这样做,则需要首先解决这个问题。


删除数据库后,如果再次创建数据库,可以执行以下命令恢复访问

GRANT CONNECT ON DATABASE thedb TO public;

每当我尝试删除数据库时,我得到:

ERROR:  database "pilot" is being accessed by other users
DETAIL:  There is 1 other session using the database.

首先你需要撤销

REVOKE CONNECT ON DATABASE TARGET_DB FROM public;

然后使用:

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB';

它肯定会起作用。

如果对机器上的其他服务没有潜在影响,只需service postgresql restart

我找到了这个问题的解决方案,尝试在终端运行这个命令

ps -ef | grep postgres

使用此命令终止进程

sudo kill -9 PID

这意味着另一个用户正在访问数据库。简单地重启PostgreSQL。这个命令就可以了

root@kalilinux:~#sudo service postgresql restart

然后尝试删除数据库:

postgres=# drop database test_database;

这样就可以了。

GUI解决方案使用pgAdmin 4

首先启用显示活动在仪表板上,如果你没有:

File > Preferences > Dashboards > Display > Show Activity > true

现在禁用所有使用db的进程:

  1. 单击DB名称
  2. 点击Dashboard >会话
  3. 点击刷新图标
  4. 单击每个进程旁边的删除(x)图标结束它们

现在应该可以删除db了。

在终端试试这个命令:

ps -ef | grep postgres

你会看到:

501 1445 3645 0 12:05AM 0:00.03 postgres: sasha dbname (本地)闲置< / p >

第三个数字(3645)是PID。

你可以删除这个

sudo kill -9 3645

然后启动PostgreSQL连接。

手动启动:

pg_ctl -D /usr/local/var/postgres start
在我的情况下,我使用AWS红移(基于Postgres)。 它似乎没有其他连接到DB,但我得到了同样的错误
ERROR:  database "XYZ" is being accessed by other users

在我的例子中,似乎数据库集群仍在对数据库进行一些处理,虽然没有其他外部/用户连接,但数据库仍在内部使用。我通过运行以下命令发现了这一点:

SELECT * FROM stv_sessions;

所以我的黑客是写一个循环在我的代码,寻找行与我的数据库名称。(当然循环不是无限的,是一个休眠循环等等)

SELECT * FROM stv_sessions where db_name = 'XYZ';

如果找到行,继续逐个删除每个PID。

SELECT pg_terminate_backend(PUT_PID_HERE);

如果没有找到行,则继续删除数据库

DROP DATABASE XYZ;

注意:在我的例子中,我正在编写Java单元/系统测试,这可以被认为是可以接受的。这对于产品代码是不可接受的。


这里是完整的破解,在Java(忽略我的测试/实用程序类)。

  int i = 0;
while (i < 10) {
try {
i++;
logStandardOut("First try to delete session PIDs, before dropping the DB");
String getSessionPIDs = String.format("SELECT stv_sessions.process, stv_sessions.* FROM stv_sessions where db_name = '%s'", dbNameToReset);
ResultSet resultSet = databaseConnection.execQuery(getSessionPIDs);
while (resultSet.next()) {
int sessionPID = resultSet.getInt(1);
logStandardOut("killPID: %s", sessionPID);
String killSessionPID = String.format("select pg_terminate_backend(%s)", sessionPID);
try {
databaseConnection.execQuery(killSessionPID);
} catch (DatabaseException dbEx) {
//This is most commonly when a session PID is transient, where it ended between my query and kill lines
logStandardOut("Ignore it, you did your best: %s, %s", dbEx.getMessage(), dbEx.getCause());
}
}


//Drop the DB now
String dropDbSQL = String.format("DROP DATABASE %s", dbNameToReset);
logStandardOut(dropDbSQL);
databaseConnection.execStatement(dropDbSQL);
break;
} catch (MissingDatabaseException ex) {
//ignore, if the DB was not there (to be dropped)
logStandardOut(ex.getMessage());
break;
} catch (Exception ex) {
logStandardOut("Something went wrong, sleeping for a bit: %s, %s", ex.getMessage(), ex.getCause());
sleepMilliSec(1000);
}
}

就这么简单

sudo service postgresql restart
< BR > < p >解决方案: 1. 关闭Pg服务器
enter image description here< BR> 2. 它将断开所有
的活动连接 3.重启Pg Server
4. Try your command

虽然我发现在其他场合投票最多的两个答案很有用,但今天,解决这个问题最简单的方法是意识到PyCharm可能会保持会话打开,如果我在PyCharm中单击Stop,这可能会有帮助。在浏览器中打开pgAdmin4后,我这样做了,几乎立即看到数据库会话统计数据降为0,此时我可以删除数据库。

在我看来,有一些空闲的查询在后台运行。

  1. 首先尝试显示正在运行的查询
SELECT pid, age(clock_timestamp(), query_start), usename, query
FROM pg_stat_activity
WHERE query != '<IDLE>' AND query NOT ILIKE '%pg_stat_activity%'
ORDER BY query_start desc;
  1. kill idle查询(检查它们是否引用有问题的数据库,或者您可以杀死所有它们或使用 来自选择结果的Pid)

选择pg_terminate_backend (procpid);

注意:杀死一个选择查询不会造成任何坏影响

REVOKE CONNECT将不阻止来自db所有者或超级用户的连接。因此,如果您不希望任何人连接db, follow命令可能会有用。

alter database pilot allow_connections = off;

然后使用:

SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'pilot';

在macOS中尝试通过控制台使用以下命令重新启动postgresql数据库:

brew services restart postgresql

停止正在运行的应用程序。(在Eclipse中)

.

.

您需要确定的是使用DB的服务没有运行。

遇到同样的问题,运行一些Java应用程序,上面的选项都不起作用,甚至不能重新启动。

使用DB运行ps aux杀死主服务。

  • 应用程序的kill -9 'PID'
  • 或者如果应用程序作为服务运行,请确保为您的操作系统运行service stop cmd。

在此之后,删除表的默认方式将完美地工作。

在我的例子中是问题

如果在IntelliJ中遇到此错误,请确保通过单击下面所示的enter image description here按钮关闭所有窗口中的连接

在我的例子中,即使在使用下面的命令之后,我仍然得到错误——因为在执行后立即创建了另一个用户连接。

REVOKE CONNECT ON DATABASE <db_name> FROM public;

什么固定它为我使用地狱的解决方案上面(也下面),以防止连接。

ALTER DATABASE <db_name> allow_connections = off

这使我可以终止流程,而无需立即重新创建流程。

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 13中更新

你可以使用这个命令删除数据库有力地,从而断开连接到它的每个用户/应用程序。

DROP DATABASE db_name WITH (FORCE)

你可以检查手册获取更多信息。

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

对我来说,我只是重新启动postgresql。

systemctl restart postgresql

第一:

sudo systemctl restart postgresql

然后:

drop database DATABASE_NAME;

如果您正在使用docker运行postgresql服务器,请重新启动容器。

这是我们在postgres 12课程中使用的方法。使用pgadmin、pgbouncer和多个客户端应用程序。

REVOKE CONNECT ON DATABASE <mydbname> FROM public;
ALTER DATABASE <mydbname> allow_connections = off;
SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '<mydbname>';
DROP DATABASE <mydbname>;

Postgresql12

流行的回答对我没有帮助。

对我来说一个不明显的解决方案:如果使用kafka/rabbit,在DROP TABLE之前禁用主管

sudo service supervisor stop