Unable to drop database postgres RDS instance - postgresql

I'm a bit confused about why I can't drop my database, so after connecting to my rds postgres instance with
psql --host=mu_user.amazonaws.com --port=5432 --username=my_user --password --dbname=postgres
I've REVOKED new connection to the db I want to drop with
REVOKE CONNECT ON DATABASE mydb FROM public;
then I have terminated all connection with
SELECT pid, pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'mydb' AND pid <> pg_backend_pid();
after that when I want to drop the db I still can't because It will say
ERROR: database "mydb" is being accessed by other users
DETAIL: There are 10 other sessions using the database.
If I inspect live connections with
SELECT
pid
,datname
,usename
,application_name
,client_hostname
,client_port
,backend_start
,query_start
,query
,state
FROM pg_stat_activity
WHERE state = 'active';
there will be none, but if I change active to idle I can see a bunch, and after trying to kill them with pg_terminate_backend(pid) I again can't drop the db and I again have the same ERROR, so can someone please help me understand what I'm I doing wrong here?
Those connections which are idle and always appearing are by my_user, who is also a superuser.

The problem is that those other connections are by a superuser, and superusers are exempt from permission checks, so revoking the CONNECT privilege on the database won't keep these guys out.
You could either block the connections via pg_hba.conf, or you can run both statements immediately after each other:
SELECT pg_terminate_backend(pid) FROM pg_stat_activity; DROP DATABASE mydb;
in the hope that the users won't have time to reconnect before the DROP DATABASE hits.

Related

Deleting a database in Postgres with DBeaver [duplicate]

I need to write a script that will drop a PostgreSQL database. There may be a lot of connections to it, but the script should ignore that.
The standard DROP DATABASE db_name query doesn't work when there are open connections.
How can I solve the problem?
This will drop existing connections except for yours:
Query pg_stat_activity and get the pid values you want to kill, then issue SELECT pg_terminate_backend(pid int) to them.
PostgreSQL 9.2 and above:
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB' -- ← change this to your DB
AND pid <> pg_backend_pid();
PostgreSQL 9.1 and below:
SELECT pg_terminate_backend(pg_stat_activity.procpid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB' -- ← change this to your DB
AND procpid <> pg_backend_pid();
Once you disconnect everyone you will have to disconnect and issue the DROP DATABASE command from a connection from another database aka not the one your trying to drop.
Note the renaming of the procpid column to pid. See this mailing list thread.
In PostgreSQL 9.2 and above, to disconnect everything except your session from the database you are connected to:
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE datname = current_database()
AND pid <> pg_backend_pid();
In older versions it's the same, just change pid to procpid. To disconnect from a different database just change current_database() to the name of the database you want to disconnect users from.
You may want to REVOKE the CONNECT right from users of the database before disconnecting users, otherwise users will just keep on reconnecting and you'll never get the chance to drop the DB. See this comment and the question it's associated with, How do I detach all other users from the database.
If you just want to disconnect idle users, see this question.
PostgreSQL 13 introduced FORCE option.
DROP DATABASE
DROP DATABASE drops a database ... Also, if anyone else is connected to the target database, this command will fail unless you use the FORCE option described below.
FORCE
Attempt to terminate all existing connections to the target database. It doesn't terminate if prepared transactions, active logical replication slots or subscriptions are present in the target database.
DROP DATABASE db_name WITH (FORCE);
Easy Peasy.
I just restart the service in Ubuntu to disconnect connected clients.
sudo service postgresql stop
sudo service postgresql start
psql
DROP DATABASE DB_NAME;
You could kill all connections before dropping the database using the pg_terminate_backend(int) function.
You can get all running backends using the system view pg_stat_activity
I'm not entirely sure, but the following would probably kill all sessions:
select pg_terminate_backend(procpid)
from pg_stat_activity
where datname = 'doomed_database'
Of course you may not be connected yourself to that database
Depending on your version of postgresql you might run into a bug, that makes pg_stat_activity to omit active connections from dropped users. These connections are also not shown inside pgAdminIII.
If you are doing automatic testing (in which you also create users) this might be a probable scenario.
In this case you need to revert to queries like:
SELECT pg_terminate_backend(procpid)
FROM pg_stat_get_activity(NULL::integer)
WHERE datid=(SELECT oid from pg_database where datname = 'your_database');
NOTE: In 9.2+ you'll have change procpid to pid.
I noticed that postgres 9.2 now calls the column pid rather than procpid.
I tend to call it from the shell:
#!/usr/bin/env bash
# kill all connections to the postgres server
if [ -n "$1" ] ; then
where="where pg_stat_activity.datname = '$1'"
echo "killing all connections to database '$1'"
else
echo "killing all connections to database"
fi
cat <<-EOF | psql -U postgres -d postgres
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
${where}
EOF
Hope that is helpful. Thanks to #JustBob for the sql.
PostgreSQL 9.2 and above:
SELECT pg_terminate_backend(pid)FROM pg_stat_activity WHERE datname = 'YOUR_DATABASE_NAME_HERE'
Here's my hack... =D
# Make sure no one can connect to this database except you!
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "UPDATE pg_database SET datallowconn=false WHERE datname='<DATABASE_NAME>';"
# Drop all existing connections except for yours!
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '<DATABASE_NAME>' AND pid <> pg_backend_pid();"
# Drop database! =D
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "DROP DATABASE <DATABASE_NAME>;"
I put this answer because include a command (above) to block new connections and because any attempt with the command...
REVOKE CONNECT ON DATABASE <DATABASE_NAME> FROM PUBLIC, <USERS_ETC>;
... do not works to block new connections!
Thanks to #araqnid #GoatWalker ! =D
https://stackoverflow.com/a/3185413/3223785
In Linux command Prompt, I would first stop all postgresql processes that are running by tying this command
sudo /etc/init.d/postgresql restart
type the command
bg to check if other postgresql processes are still running
then followed by dropdb dbname to drop the database
sudo /etc/init.d/postgresql restart
bg
dropdb dbname
This works for me on linux command prompt
In my case i had to execute a command to drop all connections including my active administrator connection
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE datname = current_database()
which terminated all connections and show me a fatal ''error'' message :
FATAL: terminating connection due to administrator command SQL state: 57P01
After that it was possible to drop the database
Nothing worked for me except, I loggined using pgAdmin4 and on the Dashboard I disconnected all connections except pgAdmin4 and then was able to rename by right lick on the database and properties and typed new name.

Cannot drop database — conflicting evidence on number of users accessing the database

On PostgreSQL 9.6.6, running on Amazon RDS
SELECT * FROM pg_stat_activity WHERE datname = 'my_db'
yields nothing.
However, trying to drop the database
DROP DATABASE my_db;
fails with:
ERROR: database "my_db" is being accessed by other users DETAIL:
There are 3 other sessions using the database.
I've tried to lock down the number of conns to the db with these two three:
REVOKE CONNECT ON DATABASE my_db FROM public;
ALTER DATABASE my_db CONNECTION LIMIT 0;
ALTER DATABASE my_db WITH ALLOW_CONNECTIONS false;
I do have read replication set up (however — this shouldn't block as this is reading off the WAL?) and occasional snapshotting (not during the DROP stmt is being run though).
What are these three lingering conns and how do I get rid of them?

Postgres drop database error: pq: cannot drop the currently open database

I'm trying to drop the database I'm currently connected to like so, but I'm getting this error:
pq: cannot drop the currently open database
I don't really understand how I'm expected to drop the database if I have to close my connection, because then I don't think I will be able to use dbConn.Exec to execute my DROP DATABASE statement?
dbConn *sql.DB
func stuff() error {
_, err := dbConn.Exec(fmt.Sprintf(`DROP DATABASE %s;`, dbName))
if err != nil {
return err
}
return dbConn.Close()
}
I guess I could connect to a different database and then execute it on that connection, but I'm not even sure if that'd work, and it seems really weird to have to connect to a new database just to drop a different database. Any ideas? Thanks.
Because, you are trying to execute dropDb command on database, to which you have open connection.
According to postgres documentation:
You cannot be connected to the database you are about to remove. Instead, connect to template1 or any other database and run this command again.
This makes sense, because when you drop the entire database, all the open connection referencing to that database becomes invalid, So the recommended approach is to connect to different database, and execute this command again.
If you are facing a situation, where a different client is connected to the database, and you really want to drop the database, you can forcibly disconnect all the client from that particular database.
For example, to forcibly disconnect all clients from database mydb:
If PostgreSQL < 9.2
SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE datname = 'mydb';
Else
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'mydb';
Note: This command requires superuser privileges.
Then, you can connect to different database, and run dropDb command again.
If you encounter this problem in IntelliJ, change the schema with the following dropdown to postgres.
After that, I was able to drop a db.
I am using PostgreSQL 12 and pgAdmin-4 in Windows 10. I had to use a combination of the above answers to drop a database, which I could not drop in pgAdmin because I was unable to close all open connections in pgAdmin.
Close pgAdmin-4.
In Windows command line, assuming my server's name is postgres and my database is mydb:
C:\> psql -U postgres
I logged in with my server password.
I then closed all open connections to mydb:
postgres-# SELECT * FROM pg_stat_activity WHERE pg_stat_activity.datname='mydb';
postgres-# SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'mydb';
Finally, I successfully dropped mydb:
postgres-# DROP DATABASE mydb;
Now if I go back into pgAdmin-4 it is gone.
To drop the database:
\c postgres
Then
DROP DATABASE your_database works
It's simple, just connect to another database \c database2. Once connected execute the drop database command while connected to the other database.
Just Connect to a different database using \c db_name;
and then drop the required database using drop database db_name;
If you are using DBeaver make sure you are not connected to the database you are trying to drop. Go to edit connections and look at the database name.
Switch the connection to a different database and then drop the database you wish.
None of this worked for me since I tried to do it through pgAdmin which kept database connections open as soon as I delete them.
Solution:
C:\Program Files\PostgreSQL\11\scripts\runpsql.bat
after you supply correct information you will be able to get pg command prompt, here you can just type:
dbdrop yourdatabase
After that you might still see database in pgAdmin but now you can just simply delete it with right click and DELETE/DROP option.
you can force to drop database with: DROP DATABASE mydb WITH (FORCE)

Terminate all connections from specific schema in certain database

With this command I can terminate all connections running in a specific database.
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'DATABASE_NAME'
AND pid <> pg_backend_pid();
Is there a way to terminate connections in a certain schema only?
No. PostgreSQL connections are always to a database, not to a schema.
Related question on dba.SE:
Force drop db while others may be connected

PostgreSQL: Temporarily disable connections

I have a script in PostgreSQL which restores test database from dump every night. The database is accessed by app servers and processes with connection pool which keeps a few connections alive at all times.
So the script restores dump into my_temp_database. Then it should rename my_database to my_old_database, my_temp_database to my_database, and eventually drop my_old_database.
How can I disconnect all clients, superuser or not, from my_database, so that it can be renamed? How I can I temporarily prevent them from reconnecting?
Is there a better way to do what I need?
To mark database 'applogs' as not accepting new connections:
update pg_database set datallowconn = false where datname = 'applogs';
Another possibility would be to revoke 'connect' access on the database for the client role(s).
Disconnect users from database = kill backend. So to disconnect all other users from "applogs" database, for example:
select pg_terminate_backend(procpid)
from pg_stat_activity
where datname = 'applogs' and procpid <> pg_backend_pid();
Once you've done both of those, you are the only user connected to 'applogs'. Although there might actually be a delay before the backends actually finish disconnecting?
After you have terminated the current active connections you can also issue this command that will only allow super users to login. This assumes you are ok with all super users having access still. Hopefully you don't hand out super user rights to just anyone.
ALTER DATABASE your_db CONNECTION LIMIT 0;
Starting PostgreSQL 9.5 we finally can:
ALTER DATABASE db WITH ALLOW_CONNECTIONS false;
I had a different usage scenario, in which I wanted to disable a DB for everyone (including superuser) and forever, but not plainly drop it just yet, to be able to reactivate it quickly if needed.
This worked fine on an old 8.3 Postgres:
UPDATE pg_database SET datallowconn=false WHERE datname='my_db_name';
If you are connected in session with the DB that you want to dissallow connecting to, and to stay connected in the same session after you disallow connections, then use this :
UPDATE pg_database SET datallowconn = false WHERE datname = '_db_name_' ;
... which allows you to do stuff without any other connection happening until you re-enable
But if you use this, it must be from in a session in another DB :
ALTER DATABASE _db_name_ WITH ALLOW_CONNECTIONS false ;
(( i realise this is almost a summary of the answers above ))