Postgresql-nie można upuścić bazy danych z powodu pewnych automatycznych połączeń do DB

Ilekroć próbuję upuścić bazę danych dostaję:

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

Kiedy używam:

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

Przerwałem połączenie z tego DB, ale jeśli spróbuję potem upuścić bazę danych, to jakoś ktoś automatycznie się do niej połączy i poda ten błąd. Co mogło to robić? Nikt nie korzysta z tej bazy danych, poza mną.

Author: Suneel Kumar, 2013-07-03

9 answers

Możesz zapobiec przyszłym połączeniom:

REVOKE CONNECT ON DATABASE thedb FROM public;

(i ewentualnie inni użytkownicy / role; zobacz \l+ w psql)

Możesz zakończyć wszystkie połączenia z tym db z wyjątkiem własnego:

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

W starszych wersjach pid był nazywany procpid więc musisz sobie z tym poradzić.

Ponieważ odebrałeś CONNECT prawa, cokolwiek próbowało połączyć się automatycznie, nie powinno być już w stanie tego zrobić.

Teraz będziesz mógł zrzucić DB.

To nie zadziała, jeśli używasz połączenia superużytkownika dla normalnych operacji, ale jeśli to robisz, musisz najpierw rozwiązać ten problem.

 79
Author: Craig Ringer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-04 04:03:28

Ilekroć próbuję upuścić bazę danych dostaję:

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

Najpierw musisz odwołać

REVOKE CONNECT ON DATABASE TARGET_DB FROM public;

Następnie użyj:

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB';
Na pewno zadziała.
 68
Author: Suneel Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-17 05:46:03

Po prostu sprawdź, co jest połączeniem, skąd pochodzi. Możesz to wszystko zobaczyć w:

select * from pg_stat_activity where datname = 'TARGET_DB';
Może to twoje połączenie?
 21
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-03 13:35:46

Znalazłem rozwiązanie tego problemu spróbuj uruchomić to polecenie w Terminalu

ps -ef | grep postgres

Zabij proces za pomocą tego polecenia

sudo kill -9 PID
 13
Author: Dinesh Pallapa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-17 11:05:42

Jeśli nie ma potencjalnego wpływu na inne usługi na Twojej maszynie, po prostu service postgresql restart

 7
Author: ScotchAndSoda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-15 10:54:12

Oznacza to, że inny użytkownik uzyskuje dostęp do bazy danych... Po prostu uruchom ponownie postgresql. To polecenie wykona sztuczkę

root@kalilinux:~#sudo service postgresql restart

Następnie spróbuj upuścić bazę danych:

postgres=# drop database accment_revamp
To wystarczy. Happy coding
 7
Author: Suman Astani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-12 09:34:51

PgAdmin 4 solution using UI

Najpierw włącz Pokaż aktywność na pulpicie nawigacyjnym, jeśli nie:

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

Teraz wyłącz wszystkie procesy za pomocą db:

  1. Kliknij nazwę DB
  2. Kliknij Dashboard > Sessions
  3. Kliknij ikonę Odśwież
  4. Kliknij ikonę Usuń (x) obok każdego procesu, aby je zakończyć

Powinny być teraz w stanie usunąć db.

 1
Author: Andrew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-16 17:39:23

W moim przypadku używam AWS Redshift(oparty na Postgres). I wygląda na to, że nie ma innych połączeń z DB, ale dostaję ten sam błąd.

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

W moim przypadku wygląda na to, że klaster baz danych nadal przetwarza dane w bazie danych i chociaż nie ma innych połączeń zewnętrznych/użytkowników, baza danych jest nadal używana wewnętrznie. Znalazłem to uruchamiając następujące:

SELECT * FROM stv_sessions;

Więc mój hack polegał na wpisaniu pętli w kodzie, szukaniu wierszy z moją bazą danych nazwisko w nim. (oczywiście pętla nie jest nieskończona i jest pętlą senną itp.)

SELECT * FROM stv_sessions where db_name = 'XYZ';

Jeśli znaleziono wiersze, Usuń każdy PID, jeden po drugim.

SELECT pg_terminate_backend(PUT_PID_HERE);

Jeśli nie znaleziono wierszy, Kontynuuj opuszczanie bazy danych

DROP DATABASE XYZ;

Uwaga: w moim przypadku piszę testy jednostkowe/systemowe Javy, gdzie można to uznać za dopuszczalne. Jest to niedopuszczalne dla kodu produkcyjnego.


Oto kompletny hack, w Javie (ignoruj moje klasy test/utility).

  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);
    }
  }
 1
Author: Sagan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-24 22:57:59

W terminalu spróbuj użyć polecenia:

ps -ef | grep postgres

Zobaczysz jak:

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

Trzecia liczba (3645) to PID.

Możesz to usunąć

sudo kill -9 3645

A następnie uruchom połączenie PostgreSQL.

Uruchom ręcznie:

pg_ctl -D /usr/local/var/postgres start
 0
Author: Alexandr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-24 21:20:48