필자의 경우 AWS Redshift (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);
}
}
GRANT CONNECT ON DATABASE thedb TO public;