Skip to content

Commit 69f37c6

Browse files
committed
fix(replication): Detect SUPERUSER connections before DROP DATABASE
When dropping an existing database, check if any connections remain after terminating regular user sessions. If SUPERUSER connections cannot be terminated (common on AWS RDS and SerenDB), fail early with a clear error message explaining the issue and resolution steps. This prevents confusing "database is being accessed by other users" errors and duplicate key violations from partial restores.
1 parent 0f1189e commit 69f37c6

3 files changed

Lines changed: 40 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [5.3.13] - 2025-12-03
6+
7+
### Fixed
8+
9+
- **Clear error message when SUPERUSER connections block DROP DATABASE**: Before attempting to drop a database, the tool now checks if any connections remain after terminating regular user sessions. If SUPERUSER connections cannot be terminated (common on AWS RDS and SerenDB), the tool now fails early with a clear error message explaining the issue and providing resolution steps, instead of letting `DROP DATABASE` fail with an obscure "database is being accessed by other users" error.
10+
511
## [5.3.12] - 2025-12-02
612

713
### Fixed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "database-replicator"
3-
version = "5.3.12"
3+
version = "5.3.13"
44
edition = "2021"
55
license = "Apache-2.0"
66
description = "Universal database-to-PostgreSQL replication CLI. Supports PostgreSQL, SQLite, MongoDB, and MySQL."

src/commands/init.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,39 @@ async fn drop_database_if_exists(target_conn: &Client, db_name: &str) -> Result<
731731
";
732732
target_conn.execute(terminate_query, &[&db_name]).await?;
733733

734+
// Check if any connections remain (including SUPERUSER connections we couldn't terminate)
735+
let remaining_query = "
736+
SELECT COUNT(*), STRING_AGG(DISTINCT sa.usename, ', ')
737+
FROM pg_stat_activity sa
738+
WHERE sa.datname = $1
739+
AND sa.pid <> pg_backend_pid()
740+
";
741+
let row = target_conn
742+
.query_one(remaining_query, &[&db_name])
743+
.await
744+
.context("Failed to check remaining connections")?;
745+
let remaining_count: i64 = row.get(0);
746+
let remaining_users: Option<String> = row.get(1);
747+
748+
if remaining_count > 0 {
749+
let users = remaining_users.unwrap_or_else(|| "unknown".to_string());
750+
bail!(
751+
"Cannot drop database '{}': {} active connection(s) from user(s): {}\n\n\
752+
These are likely SUPERUSER sessions that cannot be terminated by regular users.\n\
753+
This is common on managed PostgreSQL services (AWS RDS, SerenDB) where system\n\
754+
processes maintain superuser connections.\n\n\
755+
To resolve this:\n\
756+
1. Wait a few minutes and retry (system connections may be temporary)\n\
757+
2. Ask your database administrator to terminate the blocking sessions:\n\
758+
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '{}';\n\
759+
3. If using AWS RDS, check for RDS-managed connections in the RDS console",
760+
db_name,
761+
remaining_count,
762+
users,
763+
db_name
764+
);
765+
}
766+
734767
// Drop the database
735768
let drop_query = format!(
736769
"DROP DATABASE IF EXISTS {}",

0 commit comments

Comments
 (0)