Dans mon cas, j'utilise AWS Redshift (basé sur Postgres). Et il semble qu'il n'y ait pas d'autres connexions à la base de données, mais j'obtiens la même erreur.
ERROR: database "XYZ" is being accessed by other users
Dans mon cas, il semble que le cluster de bases de données effectue toujours un traitement sur la base de données, et bien qu'il n'y ait pas d'autres connexions externes / utilisateur, la base de données est toujours utilisée en interne. J'ai trouvé cela en exécutant ce qui suit:
SELECT * FROM stv_sessions;
Mon hack consistait donc à écrire une boucle dans mon code, à la recherche de lignes contenant le nom de ma base de données. (bien sûr, la boucle n'est pas infinie et est une boucle endormie, etc.)
SELECT * FROM stv_sessions where db_name = 'XYZ';
Si des lignes sont trouvées, procédez à la suppression de chaque PID, un par un.
SELECT pg_terminate_backend(PUT_PID_HERE);
Si aucune ligne n'est trouvée, procédez à la suppression de la base de données
DROP DATABASE XYZ;
Remarque: Dans mon cas, j'écris des tests unitaires / système Java, où cela pourrait être considéré comme acceptable. Ce n'est pas acceptable pour le code de production.
Voici le hack complet, en Java (ignorez mes classes de test / utilitaires).
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;