Postgresql - não é possível descartar o banco de dados devido a algumas conexões automáticas ao banco de dados

162

Sempre que tento descartar o banco de dados, recebo:

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

Quando eu uso:

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

Eu encerrei a conexão desse banco de dados, mas se eu tentar descartar o banco de dados depois disso, alguém de alguma forma se conectará automaticamente a esse banco de dados e fornecerá esse erro. O que poderia estar fazendo isso? Ninguém usa esse banco de dados, exceto eu.

Andrius
fonte

Respostas:

196

Você pode impedir conexões futuras:

REVOKE CONNECT ON DATABASE thedb FROM public;

(e possivelmente outros usuários / funções; veja \l+em psql)

Você pode terminar todas as conexões com este banco de dados, exceto a sua:

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

Nas versões mais antigas pidfoi chamado, procpidentão você terá que lidar com isso.

Como você revogou os CONNECTdireitos, o que quer que estivesse tentando se conectar automaticamente não deveria mais ser capaz de fazê-lo.

Agora você poderá soltar o banco de dados.

Isso não funcionará se você estiver usando conexões de superusuário para operações normais, mas se estiver fazendo isso, precisará corrigir esse problema primeiro.


Após terminar de descartar o banco de dados, se você criar o banco de dados novamente, poderá executar o comando abaixo para restaurar o acesso

GRANT CONNECT ON DATABASE thedb TO public;
Craig Ringer
fonte
19
Se você importar outro banco de dados com o mesmo nome depois, conceder a capacidade de conexão para trás público:GRANT CONNECT ON DATABASE thedb TO public;
Mikhail Vasin
156

Sempre que tento descartar o banco de dados, recebo:

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

Primeiro você precisa revogar

REVOKE CONNECT ON DATABASE TARGET_DB FROM public;

Então use:

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

Certamente funcionará.

Suneel Kumar
fonte
5
Isso fez por mim. Graças
rpivovar
1
Spot on! Obrigado! 🎉
slajma 03/04
1
Funcionou perfeito. Obrigado.
Mustafa Magdi 13/04
34

Encontrei uma solução para este problema tente executar este comando no terminal

ps -ef | grep postgres

processo de morte por este comando

sudo kill -9 PID
Dinesh Pallapa
fonte
Não, é muito difícil, e se você não puder processar o kiil pg porque possui outros bancos de dados que estão sendo acessados?
Vladimir Stazhilov 13/03/19
2
@VladimirStazhilov Ele mostrará o nome do banco de dados e o pid desse banco de dados. alguém pode selecionar pid kill específico apenas nesse banco de dados específico.
Dinesh Pallapa
29

Basta verificar qual é a conexão, de onde ela está vindo. Você pode ver tudo isso em:

select * from pg_stat_activity where datname = 'TARGET_DB';

Talvez seja a sua conexão?


fonte
4
sudo kill -9 PID no Terminal depois de ver o resultado
Dan Rey Oquindo
25

Isso significa que outro usuário está acessando o banco de dados. Simplesmente reinicie o PostgreSQL. Este comando fará o truque

root@kalilinux:~#sudo service postgresql restart

Em seguida, tente soltar o banco de dados:

postgres=# drop database test_database;

Isto irá fazer o truque.

Suman Astani
fonte
11

Solução pgAdmin 4 usando interface do usuário

Primeiro ative a atividade show no painel, se você não tiver:

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

Agora desative todos os processos usando o db:

  1. Clique no nome do banco de dados
  2. Clique em Painel> Sessões
  3. Clique no ícone de atualização
  4. Clique no ícone excluir (x) ao lado de cada processo para finalizá-los

Agora deve ser capaz de excluir o banco de dados.

Andrew
fonte
Isso funciona bem - eu testei com o PgAdmin 4.5 e com o PostgreSQL 11.2, compilado pelo Visual C ++ build 1914, 64 bits (Windows).
Vab2048 #
2
Esta é a melhor solução que eu acho. Isso funciona muito bem!
Lahiru 9/01
10

Se não houver impacto potencial em outros serviços em sua máquina, basta service postgresql restart

ScotchAndSoda
fonte
8

Solução:
1. Desligue o servidor Pg 2. Ele desconectará todas as conexões ativas 3. Reinicie o servidor Pg 4. Tente seu comando
insira a descrição da imagem aqui



amoljdv06
fonte
isso funcionou para mim também com o Postgress.app em um Mac. Nesse caso, você para / inicia o servidor
Juan José Ramírez
7

Simples assim

sudo service postgresql restart
OdkoPP
fonte
3

No meu caso, estou usando o AWS Redshift (baseado no Postgres). E parece que não há outras conexões com o banco de dados, mas estou recebendo esse mesmo erro.

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

No meu caso, parece que o cluster do banco de dados ainda está processando no banco de dados e, embora não haja outras conexões externas / de usuários, o banco de dados ainda está em uso internamente. Encontrei isso executando o seguinte:

SELECT * FROM stv_sessions;

Então, meu truque foi escrever um loop no meu código, procurando linhas com o nome do meu banco de dados. (é claro que o loop não é infinito e é um loop sonolento, etc.)

SELECT * FROM stv_sessions where db_name = 'XYZ';

Se houver linhas, prossiga para excluir cada PID, um por um.

SELECT pg_terminate_backend(PUT_PID_HERE);

Se nenhuma linha for encontrada, prossiga para descartar o banco de dados

DROP DATABASE XYZ;

Nota: No meu caso, estou escrevendo testes de unidade / sistema Java, onde isso pode ser considerado aceitável. Isso não é aceitável para o código de produção.


Aqui está o hack completo, em Java (ignore minhas classes de teste / utilitário).

  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);
    }
  }
Sagan
fonte
2

Na minha opinião, existem algumas consultas ociosas em execução no backgroud.

  1. Tente mostrar as consultas em execução primeiro
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 (verifique se eles estão fazendo referência ao banco de dados em questão ou se você pode matar todos eles ou matar um específico usando o pid dos resultados selecionados)

SELECT pg_terminate_backend (procpid);

Nota: Matar uma consulta selecionada não causa nenhum impacto ruim

Joweria
fonte
2

REVOKE CONNECTnão impedirá as conexões do proprietário ou superusuário do banco de dados. Portanto, se você não deseja que ninguém conecte o banco de dados, o comando follow pode ser útil.

alter database pilot allow_connections = off;

Então use:

SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'pilot';
inferno
fonte
1
Obrigado ... REVOKE CONNECT não foi suficiente no meu cenário.
volpato 4/06
1

Embora eu tenha achado as duas respostas votadas com êxito úteis em outras ocasiões, hoje, a maneira mais simples de resolver o problema era perceber que o PyCharm pode estar mantendo uma sessão aberta e, se eu clicar Stopem PyCharm, isso pode ajudar. Com o pgAdmin4 aberto no navegador, eu o fiz e quase imediatamente vi as estatísticas das sessões do Banco de Dados caírem para 0, momento em que consegui soltar o banco de dados.

hlongmore
fonte
"PyCharm pode estar mantendo uma sessão aberta"? Quão? Eu executo testes de unidade no terminal do PyCharm (front-end do Python com peewee, back-end do Postgres), ou seja, o botão "Stop" fica acinzentado e mantenho esses erros ...
Laryx Decidua
@LaryxDecidua Acredito que, no meu caso, devo ter uma instância de um serviço em execução no PyCharm que usava o banco de dados. Se você sair do PyCharm, o número de instâncias cai para 0, permitindo que você elimine o banco de dados? Nesse caso, deve haver algo (explorador de banco de dados, consulta SQL, outra coisa) que ainda esteja conectado.
hlongmore 13/03
1

No macOS, tente reiniciar o banco de dados postgresql através do console usando o comando:

brew services restart postgresql
Felipe Corredor
fonte
-1

No terminal, tente este comando:

ps -ef | grep postgres

você verá como:

501 1445 3645 0 00:05 0: 00.03 postgres: sasha dbname [local] ocioso

O terceiro número (3645) é PID.

Você pode excluir este

sudo kill -9 3645

E depois disso, inicie sua conexão com o PostgreSQL.

Comece manualmente:

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