Trong trường hợp của tôi, tôi đang sử dụng AWS Redshift (dựa trên Postgres). Và có vẻ như không có kết nối nào khác với DB, nhưng tôi cũng gặp lỗi tương tự.
ERROR: database "XYZ" is being accessed by other users
Trong trường hợp của tôi, có vẻ như cụm cơ sở dữ liệu vẫn đang thực hiện một số xử lý trên cơ sở dữ liệu và trong khi không có kết nối bên ngoài / người dùng nào khác, cơ sở dữ liệu vẫn được sử dụng nội bộ. Tôi tìm thấy điều này bằng cách chạy như sau:
SELECT * FROM stv_sessions;
Vì vậy, hack của tôi là viết một vòng lặp trong mã của tôi, tìm kiếm các hàng có tên cơ sở dữ liệu của tôi trong đó. (tất nhiên vòng lặp không phải là vô hạn và là vòng lặp buồn ngủ, v.v.)
SELECT * FROM stv_sessions where db_name = 'XYZ';
Nếu hàng được tìm thấy, tiến hành xóa từng PID, từng cái một.
SELECT pg_terminate_backend(PUT_PID_HERE);
Nếu không tìm thấy hàng, tiến hành thả cơ sở dữ liệu
DROP DATABASE XYZ;
Lưu ý: Trong trường hợp của tôi, tôi đang viết các bài kiểm tra đơn vị / hệ thống Java, trong đó điều này có thể được coi là chấp nhận được. Điều này không được chấp nhận cho mã sản xuất.
Đây là bản hack hoàn chỉnh, trong Java (bỏ qua các lớp kiểm tra / tiện ích của tôi).
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;