Postgresql - unable to drop database because of some auto connections to DB
Asked Answered
R

25

313

Whenever I try to drop database I get the following error:

ERROR:  database "pilot" is being accessed by other users
DETAIL:  There is 1 other session using the database.

When I use:

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB';

I terminated the connection from that DB, but if I try to drop database after that somehow someone automatically connects to that database and gives this error. What could be doing that? No one uses this database, except me.

Reflection answered 3/7, 2013 at 13:32 Comment(0)
C
346

Postgres 13+

Use WITH (force)

See https://mcmap.net/q/99112/-postgresql-unable-to-drop-database-because-of-some-auto-connections-to-db instead

Postgres 12 and older

You can prevent future connections with:

REVOKE CONNECT ON DATABASE thedb FROM public;

(and possibly other users/roles; see \l+ in psql)

You can then terminate all connections to this db except your own:

SELECT pid, pg_terminate_backend(pid) 
FROM pg_stat_activity 
WHERE datname = current_database() AND pid <> pg_backend_pid();

On older versions pid was called procpid so you'll have to deal with that.

Since you've revoked CONNECT rights, whatever was trying to auto-connect should no longer be able to do so.

You'll now be able to drop the DB.

This won't work if you're using superuser connections for normal operations, but if you're doing that you need to fix that problem first.


After you're done dropping the database, if you create the database again, you can execute below command to restore the access

GRANT CONNECT ON DATABASE thedb TO public;
Cacka answered 4/7, 2013 at 4:3 Comment(5)
If you import another database with the same name later, grant connect capability to public back: GRANT CONNECT ON DATABASE thedb TO public;Reverse
REVOKE CONNECT will not prevent the connections from the db owner or superuser. So if you don't want anyone to connect the db, execute command alter database pilot allow_connections = off. https://mcmap.net/q/99112/-postgresql-unable-to-drop-database-because-of-some-auto-connections-to-dbBottrop
This is a way to do this, but Postgresql 13 update with FORCE, shortens the way a lot. Check my answer or the manual.Huxley
current_database() not working for me but this is ok (db_name in single quotes): SELECT pid, pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'db_name' AND pid <> pg_backend_pid();Thaler
As of Postgres 13 there is a MUCH easier way using WITH (FORCE): https://mcmap.net/q/99112/-postgresql-unable-to-drop-database-because-of-some-auto-connections-to-dbTon
O
256

Whenever I try to drop database I get:

ERROR:  database "pilot" is being accessed by other users
DETAIL:  There is 1 other session using the database.

First You need to revoke

REVOKE CONNECT ON DATABASE TARGET_DB FROM public;

Then use:

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB';

It will surely work.

Oldtimer answered 17/7, 2014 at 5:46 Comment(2)
The final SQL statement, may require to be run multiple times, depending on the the number of sessions using the database at the time. Overall this approach work perfectly.Relax
under docker-compose if you use the db dbname, this doesn't help as psql is connecting to the db it seems, so you still can't drop. i am unsure.Spermous
H
78

Update in Postgresql 13

You could just use this command to drop a Database forcefully, thus disconnecting each user/app connected to it.

DROP DATABASE db_name WITH (FORCE)

You could check the manual for more.

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.

PS: You cannot delete the database that you are connected to while executing this query.

Huxley answered 30/8, 2021 at 10:7 Comment(2)
This works great, as long as you are connected to a different database when you run it. Otherwise you get an error that you can't delete the currently connected DB.Ton
This is the best!Minicam
F
53

I found a solution for this problem try to run this command in terminal

ps -ef | grep postgres

kill process by this command

sudo kill -9 PID
Floatable answered 17/10, 2017 at 11:5 Comment(3)
No, it's too hardcode, what if you can't kiil pg process because you have other databases that are being accessed?Alexisaley
@VladimirStazhilov It will show the database name and pid of that database. someone can select specific pid kill only that particular database.Floatable
ps -ef | grep postgres | grep YourAppName | cut -w -f3 | xargs kill -9Nosy
P
51

It means another user is accessing the database. Simply restart PostgreSQL. This command will do the trick

root@kalilinux:~#sudo service postgresql restart

Then try dropping the database:

postgres=# drop database test_database;

This will do the trick.

Pathetic answered 12/3, 2018 at 9:34 Comment(3)
hey tysm this worked for me. I will like to add if you have a hyphen - in the name of the db put it in quotation marks like this "my-database"Greenery
This is a great and simple solution!Dominquedominquez
This would be good if it is used in a dev environment. It is exactly what you need in this case. However, as far as scripting for production, there may be other considerations as have been pointed out in above solutions.Electro
M
45

Simply check what is the connection, where it's coming from. You can see all this in:

SELECT * FROM pg_stat_activity WHERE datname = 'TARGET_DB';

Perhaps it is your connection?

Matthia answered 3/7, 2013 at 13:35 Comment(1)
sudo kill -9 PID in terminal after seeing the resultPerusse
E
30

GUI solution using pgAdmin 4

First enable show activity on dashboard if you haven't:

File > Preferences > Dashboards > Display > Show Activity > true

Now disable all the processes using the db:

  1. Click the DB name
  2. Click Dashboard > Sessions
  3. Click refresh icon
  4. Click the delete (x) icon beside each process to end them

You should now be able to delete the db.

Epic answered 16/7, 2018 at 14:0 Comment(3)
This works well - I tested it with PgAdmin 4.5 and with PostgreSQL 11.2, compiled by Visual C++ build 1914, 64-bit (Windows).Chinook
This is the best solution I think. This works really well!Accord
To view the Dashboard, right-click on the top menu and choose Add Panel -> DashboardInae
A
15

If no potential impact on other services on your machine, simply service postgresql restart

Angelinaangeline answered 15/5, 2017 at 10:54 Comment(0)
P
13

In macOS try to restart postgresql database through the console using the command:

brew services restart postgresql
Psychosocial answered 16/7, 2020 at 4:21 Comment(1)
yea, I use postgres.app and restarting the server fixed it.Files
S
12

Solution:
1. Shut down Pg server
enter image description here
2. It will disconnect all active connection
3. Restart Pg Server
4. Try your command

Shanley answered 4/12, 2018 at 7:29 Comment(1)
this worked for me too with Postgress.app on a Mac. In that case you stop/start the serverGros
L
10

Simple as that

sudo service postgresql restart
Levant answered 15/10, 2018 at 22:57 Comment(0)
B
6

REVOKE CONNECT will not prevent the connections from the db owner or superuser. So if you don't want anyone to connect the db, follow command may be useful.

alter database pilot allow_connections = off;

Then use:

SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'pilot';
Bottrop answered 12/5, 2020 at 8:13 Comment(3)
Thanks... REVOKE CONNECT was not enough on my scenario.Dachau
# alter database dbname allow_connections = off; ERROR: cannot disallow connections for current databaseSpermous
@Eugene Gr. Philippov you can not alter database that you are logged in, so you should change to other database and retry.Bottrop
S
6

This is what worked for us on postgres 12. Using pgadmin, pgbouncer, and multiple client applications.

REVOKE CONNECT ON DATABASE <mydbname> FROM public;
ALTER DATABASE <mydbname> allow_connections = off;
SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '<mydbname>';
DROP DATABASE <mydbname>;
Sideway answered 5/4, 2022 at 13:16 Comment(1)
You may need GRANT pg_signal_backend TO <user name>; to be able to do that.Unpremeditated
E
5

first:

sudo systemctl restart postgresql

then:

drop database DATABASE_NAME;
Epigrammatist answered 4/1, 2022 at 9:32 Comment(1)
While this may be factually correct, adding explanation would vastly improve the answer.Epic
I
4

In my case, I am using AWS Redshift (based on Postgres). And it appears there are no other connections to the DB, but I am getting this same error.

ERROR:  database "XYZ" is being accessed by other users

In my case, it seems the database cluster is still doing some processing on the database, and while there are no other external/user connections, the database is still internally in use. I found this by running the following:

SELECT * FROM stv_sessions;

So my hack was to write a loop in my code, looking for rows with my database name in it. (of course the loop is not infinite, and is a sleepy loop, etc)

SELECT * FROM stv_sessions where db_name = 'XYZ';

If rows found, proceed to delete each PID, one by one.

SELECT pg_terminate_backend(PUT_PID_HERE);

If no rows found, proceed to drop the database

DROP DATABASE XYZ;

Note: In my case, I am writing Java unit/system tests, where this could be considered acceptable. This is not acceptable for production code.


Here is the complete hack, in Java (ignore my test/utility classes).

  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);
    }
  }
Incommunicable answered 19/9, 2018 at 19:56 Comment(1)
This should be correct answer, others those who restart service, why not restart your computer?Impertinent
M
4

In my opinion there are some idle queries running in the backgroud.

  1. Try showing running queries first
SELECT pid, age(clock_timestamp(), query_start), usename, query 
FROM pg_stat_activity 
WHERE query != '<IDLE>' AND query NOT ILIKE '%pg_stat_activity%' 
ORDER BY query_start desc;
  1. kill idle query ( Check if they are referencing the database in question or you can kill all of them or kill a specific using the pid from the select results )

SELECT pg_terminate_backend(procpid);

Note: Killing a select query doesnt make any bad impact

Mom answered 25/10, 2019 at 16:19 Comment(0)
F
2

If you are using docker to run postgresql server, restart the container.

Furfur answered 26/1, 2022 at 11:40 Comment(0)
A
1

If you encounter this error in IntelliJ make sure you close the connection in all windows by clicking the button shown below enter image description here

Aliber answered 26/4, 2021 at 8:22 Comment(0)
B
1

In my case, I continued to get the error even after using the below command - because another user connection was immediately created after execution.

REVOKE CONNECT ON DATABASE <db_name> FROM public;

What fixed it for me was using inferno's solution above (also below) to prevent connections.

ALTER DATABASE <db_name> allow_connections = off

That allowed me to terminate the process without the process immediately being recreated.

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();

Blow answered 19/6, 2021 at 20:6 Comment(0)
S
0

While I found the two top-upvoted answers useful on other occasions, today, the simplest way to resolve the issue was to realize that PyCharm might be keeping a session open, and if I clicked Stop in PyCharm, that might help. With pgAdmin4 open in the browser, I did so, and almost immediately saw the Database sessions stats drop to 0, at which point I was able to drop the database.

Shovel answered 24/12, 2018 at 6:44 Comment(2)
"PyCharm might be keeping a session open" ? How? I run unit tests in PyCharm's terminal (frontend Python with peewee, backend Postgres) , i.e. the "Stop" button is greyed out and I keep these errors nevertheless...Canikin
@LaryxDecidua I believe that, in my case, I must have had an instance of a service running in PyCharm that used the db. If you exit PyCharm, does the number of instances drop to 0, allowing you to drop the db? If so, there must be something (database explorer, SQL query, something else) that is still connected.Shovel
D
0

For me, I just restart postgresql.

systemctl restart postgresql
Donyadoodad answered 30/10, 2021 at 1:45 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Fantasize
F
0

Postgresql12

Popular answer dont help for me.

An unobvious solution for me: disabling the supervisor before DROP TABLE, if use kafka/rabbit

sudo service supervisor stop
Flush answered 1/7, 2022 at 6:39 Comment(0)
T
-1

In terminal try this command:

ps -ef | grep postgres

you will see like:

501 1445 3645 0 12:05AM 0:00.03 postgres: sasha dbname [local] idle

The third number (3645) is PID.

You can delete this

sudo kill -9 3645

And after that start your PostgreSQL connection.

Start manually:

pg_ctl -D /usr/local/var/postgres start
Theosophy answered 24/8, 2018 at 21:20 Comment(1)
I am not the one downvoting, but guessing this is due to this being a duplicate and due to using a dangerous solution.Bulwark
E
-1

Stop your running application.(in Eclipse) After you try again.

Epicycle answered 7/10, 2020 at 11:9 Comment(1)
Please add more details with the answers to help with the solution along with the failure reason.Miracle
C
-1

What you need to be certain is that the service using the DB is not running.

Experienced same issue, running some Java apps, and none of the above options worked, not even restart.

Run a ps aux kill the main service using the DB.

  • kill -9 'PID' of the application
  • or if the application runs as a service make sure to run the service stop cmd for your OS.

After that the default way to drop a table will work flawlessly.

In my example were issues with

Claudiaclaudian answered 7/11, 2020 at 2:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.