在我的情况下,我正在使用基于Postgres的AWS Redshift。
并且似乎没有其他对数据库的连接,但我仍然收到相同的错误。
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);
}
}
GRANT pg_signal_backend TO <用户名>;
才能实现该操作。 - iMx