In meinem Fall verwende ich AWS Redshift (basierend auf Postgres). Und es scheint, dass es keine anderen Verbindungen zur Datenbank gibt, aber ich erhalte den gleichen Fehler.
ERROR: database "XYZ" is being accessed by other users
In meinem Fall scheint der Datenbankcluster noch einige Verarbeitungsvorgänge für die Datenbank durchzuführen, und obwohl keine anderen externen / Benutzerverbindungen bestehen, wird die Datenbank weiterhin intern verwendet. Ich habe dies gefunden, indem ich Folgendes ausgeführt habe:
SELECT * FROM stv_sessions;
Mein Hack bestand also darin, eine Schleife in meinen Code zu schreiben und nach Zeilen mit meinem Datenbanknamen zu suchen. (Natürlich ist die Schleife nicht unendlich und ist eine verschlafene Schleife usw.)
SELECT * FROM stv_sessions where db_name = 'XYZ';
Wenn Zeilen gefunden wurden, löschen Sie jede PID nacheinander.
SELECT pg_terminate_backend(PUT_PID_HERE);
Wenn keine Zeilen gefunden wurden, löschen Sie die Datenbank
DROP DATABASE XYZ;
Hinweis: In meinem Fall schreibe ich Java-Unit- / Systemtests, bei denen dies als akzeptabel angesehen werden kann. Dies ist für den Produktionscode nicht akzeptabel.
Hier ist der komplette Hack in Java (ignoriere meine Test- / Utility-Klassen).
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;