Postgresql-невозможно удалить базу данных из-за некоторых автоматических подключений к БД



всякий раз, когда я пытаюсь удалить базу данных, я получаю:



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


когда я использую:



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


Я прекратил соединение с этой БД, но если я попытаюсь удалить базу данных после этого, кто-то автоматически подключится к этой базе данных и даст эту ошибку. Что может быть, что делать?
Никто не использует эту базу данных, кроме меня.

4055   9  

9 ответов:

вы можете предотвратить будущие соединения:

REVOKE CONNECT ON DATABASE thedb FROM public;

(и, возможно, другие пользователи и роли; см. \l+ на psql)

затем вы можете завершить все подключения к этой БД, кроме собственного:

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

на старых версиях pid называлась procpid так что вам придется смириться с этим.

так как вы отозвали CONNECT права, все, что пытается автоматически подключиться, больше не должно быть в состоянии сделать это.

теперь вы сможете отбросить ДЕЦИБЕЛ.

это не будет работать, если вы используете суперпользовательские соединения для обычных операций, но если вы делаете это, вам нужно сначала решить эту проблему.

всякий раз, когда я пытаюсь удалить базу данных, я получаю:

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

сначала вам нужно отменить

REVOKE CONNECT ON DATABASE TARGET_DB FROM public;

затем использовать:

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

это наверняка сработает.

просто проверьте, что такое соединение, откуда оно исходит. Вы можете увидеть все это в:

select * from pg_stat_activity where datname = 'TARGET_DB';

возможно, это ваша связь?

Я нашел решение этой проблемы попробуйте запустить эту команду в терминале

ps -ef | grep postgres

убить процесс по этой команде

sudo kill -9 PID

если нет потенциального влияния на другие службы на вашем компьютере, просто service postgresql restart

Это означает, что другой пользователь обращается к базе данных... Просто перезапустите postgresql. Эта команда будет делать трюк

root@kalilinux:~#sudo service postgresql restart

затем попробуйте удалить базу данных:

postgres=# drop database accment_revamp

это будет делать трюк. Счастливого кодирования

pgAdmin 4 решение с помощью UI

сначала включите показать активность на приборной панели, если у вас нет:

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

теперь отключите все процессы, использующие БД:

  1. щелкните имя БД
  2. Щелкните Панель Мониторинга > Сеансы
  3. Нажмите кнопку "Обновить" значок
  4. щелкните значок Удалить (x) рядом с каждым процессом, чтобы завершить их

теперь должна быть возможность удалить БД.

в моем случае я использую AWS Redshift (на основе Postgres). И, кажется, нет никаких других подключений к БД, но я получаю эту же ошибку.

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

в моем случае кажется, что кластер баз данных все еще выполняет некоторую обработку в базе данных, и хотя нет других внешних/пользовательских подключений, база данных все еще используется внутри. Я нашел это, выполнив следующее:

SELECT * FROM stv_sessions;

так что мой Хак должен был написать цикл в моем коде, ища строки с моим именем базы данных в нем. (конечно, цикл не бесконечен, а является сонным циклом и т. д.)

SELECT * FROM stv_sessions where db_name = 'XYZ';

если строки найдены, перейдите к удалению каждого PID, один за другим.

SELECT pg_terminate_backend(PUT_PID_HERE);

если строки не найдены, перейдите к удалению базы данных

DROP DATABASE XYZ;

Примечание: В моем случае я пишу тесты Java unit/system, где это можно считать приемлемым. Это неприемлемо для производственного кода.


вот полный Хак, в Java (игнорировать мои тестовые / служебные классы).

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

в терминале попробуйте эту команду:

ps -ef | grep postgres

вы увидите как:

501 1445 3645 0 12: 05AM 0: 00.03 postgres: sasha dbname [местный] холостом ходу

третий номер (3645) - PID.

вы можете удалить этот

sudo kill -9 3645

и после этого запустите соединение PostgreSQL.

запустить вручную:

pg_ctl -D /usr/local/var/postgres start

Comments

    Ничего не найдено.