Mate uma sessão / conexão postgresql

370

Como posso matar todas as minhas conexões postgresql?

Estou tentando, rake db:dropmas recebo:

ERROR:  database "database_name" is being accessed by other users
DETAIL:  There are 1 other session(s) using the database.

Eu tentei desligar os processos que vejo de um, ps -ef | grep postgresmas isso também não funciona:

kill: kill 2358 failed: operation not permitted
DanS
fonte
Quando todas as outras tentativas falharam, a gema pgreset de alguma forma corrigiu rails / pg pensando que existia uma conexão, o que não ocorreu.
JosephK

Respostas:

672

Você pode usar pg_terminate_backend () para matar uma conexão. Você precisa ser superusuário para usar esta função. Isso funciona em todos os sistemas operacionais da mesma forma.

SELECT 
    pg_terminate_backend(pid) 
FROM 
    pg_stat_activity 
WHERE 
    -- don't kill my own connection!
    pid <> pg_backend_pid()
    -- don't kill the connections to other databases
    AND datname = 'database_name'
    ;

Antes de executar esta consulta, você deve REVOGAR os privilégios CONNECT para evitar novas conexões:

REVOKE CONNECT ON DATABASE dbname FROM PUBLIC, username;

Se você estiver usando o Postgres 8.4-9.1, use procpid em vez de pid

SELECT 
    pg_terminate_backend(procpid) 
FROM 
    pg_stat_activity 
WHERE 
    -- don't kill my own connection!
    procpid <> pg_backend_pid()
    -- don't kill the connections to other databases
    AND datname = 'database_name'
    ;
Frank Heikens
fonte
68
Note que no Postgres 9.2, procpid é renomeado para pid.
Devin
Se ele era um superusuário, ele não poderia ter sudomorrido de qualquer maneira?
Ndnenkov 11/03/16
3
@ndn Um superusuário de banco de dados não é a mesma coisa que um superusuário no nível do SO. Não existe sudono PG.
Jpmc26 29/07
Esta é a única resposta de trabalho para muitas perguntas de SO, porque tem o REVOKEpasso. Você salvou alguém, mais uma vez, eu acho!
AymDev
Isso funciona graças ....
Ajay Kumar
205

Talvez apenas reinicie postgres=>sudo service postgresql restart

Haris Krajina
fonte
@Starkers eu passei a maior parte respostas acima, até que me dei conta :)
Haris Krajina
32
@Starkers Sim, especialmente seguro em produção sob alta carga;)
Erathiel
10
brew services restart postgresqlse vc tem cerveja
Sam Kah Chiin
28

Com todas as informações sobre o processo em execução:

SELECT *, pg_terminate_backend(pid)
FROM pg_stat_activity 
WHERE pid <> pg_backend_pid()
AND datname = 'my_database_name';
Dorian
fonte
13

OSX, Postgres 9.2 (instalado com homebrew)

$ launchctl unload -w ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist
$ pg_ctl restart -D /usr/local/var/postgres
$ launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist


Se o seu datadir estiver em outro lugar, você poderá descobrir onde está examinando a saída de ps aux | grep postgres

artemave
fonte
4
Oubrew services restart postgresql
PJSCopeland
@PJSCopeland Obrigado pela solução mais simples! Eu acho que o seu comentário merece ser uma resposta real, assim: stackoverflow.com/a/48226667/1097104
Juuso Ohtonen
Obrigado por isso, @JuusoOhtonen. Mas, se você quer a reputação dela, poderia pelo menos vincular o meu comentário?
PJSCopeland
@PJSCopeland Done.
Juuso Ohtonen 15/01/19
Teve problemas com outras respostas e outras soluções SO post similares. Executando o seu pg_ctl restart -D /usr/local/var/postgresfez o truque! (Eu nem executei o primeiro ou o terceiro comando).
Iggy
8

Isso parece estar funcionando para o PostgreSQL 9.1:

#{Rails.root}/lib/tasks/databases.rake
# monkey patch ActiveRecord to avoid There are n other session(s) using the database.
def drop_database(config)
  case config['adapter']
  when /mysql/
    ActiveRecord::Base.establish_connection(config)
    ActiveRecord::Base.connection.drop_database config['database']
  when /sqlite/
    require 'pathname'
    path = Pathname.new(config['database'])
    file = path.absolute? ? path.to_s : File.join(Rails.root, path)

    FileUtils.rm(file)
  when /postgresql/
    ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
    ActiveRecord::Base.connection.select_all("select * from pg_stat_activity order by procpid;").each do |x|
      if config['database'] == x['datname'] && x['current_query'] =~ /<IDLE>/
        ActiveRecord::Base.connection.execute("select pg_terminate_backend(#{x['procpid']})")
      end
    end
    ActiveRecord::Base.connection.drop_database config['database']
  end
end

Levantado das essência encontradas aqui e aqui .

Aqui está uma versão modificada que funciona para o PostgreSQL 9.1 e 9.2.

Chris
fonte
6

Eu uso a seguinte tarefa de rake para substituir o drop_databasemétodo Rails .

lib/database.rake

require 'active_record/connection_adapters/postgresql_adapter'
module ActiveRecord
  module ConnectionAdapters
    class PostgreSQLAdapter < AbstractAdapter
      def drop_database(name)
        raise "Nah, I won't drop the production database" if Rails.env.production?
        execute <<-SQL
          UPDATE pg_catalog.pg_database
          SET datallowconn=false WHERE datname='#{name}'
        SQL

        execute <<-SQL
          SELECT pg_terminate_backend(pg_stat_activity.pid)
          FROM pg_stat_activity
          WHERE pg_stat_activity.datname = '#{name}';
        SQL
        execute "DROP DATABASE IF EXISTS #{quote_table_name(name)}"
      end
    end
  end
end

Edit: Isto é para Postgresql 9.2+

Chris Aitchison
fonte
Você precisa usar em pg_stat_activity.procpidvez do pg_stat_activity.pidPostgres 9.1 e abaixo. Veja stackoverflow.com/a/5408501/444774
talyric
11
Esta é uma ótima resposta! É melhor e mais seguro que o padrão do Rails. Obrigado!
Piersadrian
5

A maneira mais fácil e atualizada é:

  1. Use ps -ef | grep postgrespara encontrar a conexão #
  2. sudo kill -9 "#" da conexão

Nota: Pode haver PID idêntico. Matar um mata todos.

Mr. Rene
fonte
3

Eu tive esse problema e o problema era que o Navicat estava conectado ao meu banco de dados local do Postgres. Depois de desconectar o Navicat, o problema desapareceu.

EDITAR:

Além disso, como último recurso absoluto, você pode fazer backup de seus dados e executar este comando:

sudo kill -15 `ps -u postgres -o pid`

... o que matará tudo o que o usuário do postgres está acessando. Evite fazer isso em uma máquina de produção, mas você não deve ter problemas com um ambiente de desenvolvimento. É vital que você garanta que todos os postgres processos realmente tenham terminado antes de tentar reiniciar o PostgreSQL depois disso.

EDIT 2:

Devido a esta postagem do unix.SE, mudei de kill -9para kill -15.

Jamon Holmgren
fonte
11
Na minha experiência limitada com o Navicat Lite, simplesmente fechar o banco de dados ou a conexão do servidor nem sempre é suficiente. O Navicat Lite parece manter a conexão ocasional aberta até que o aplicativo seja encerrado.
ken
3

Eu resolvi desta maneira:

No meu Windows8 de 64 bits, apenas restarto serviço: postgresql-x64-9.5

X-Coder
fonte
5
Isso é apenas uma reinicialização que geralmente não é desejável para ambientes de produção, matar o processo de abraço é uma opção muito mais desejável.
BrianC
3
SELECT 
pg_terminate_backend(pid) 
FROM 
pg_stat_activity 
WHERE
pid <> pg_backend_pid()
-- no need to kill connections to other databases
AND datname = current_database();
-- use current_database by opening right query tool
Janki
fonte
1

Só queria salientar que a Resposta de Haris pode não funcionar se algum outro processo em segundo plano estiver usando o banco de dados; no meu caso, foram trabalhos atrasados, eu fiz:

script/delayed_job stop

E só então eu fui capaz de soltar / redefinir o banco de dados.

mlabarca
fonte
1

Saia do postgres e reinicie-o. Simples, mas funciona sempre para mim, onde outros comandos cli às vezes não.

Stan Amsellem
fonte
Simples e funciona! Para esclarecer melhor bastante pgAdmin 4 e restart
Ka tecnologia
0

Não há necessidade de abandoná-lo. Basta excluir e recriar o esquema público. Na maioria dos casos, isso tem exatamente o mesmo efeito.

namespace :db do

desc 'Clear the database'
task :clear_db => :environment do |t,args|
  ActiveRecord::Base.establish_connection
  ActiveRecord::Base.connection.tables.each do |table|
    next if table == 'schema_migrations'
    ActiveRecord::Base.connection.execute("TRUNCATE #{table}")
  end
end

desc 'Delete all tables (but not the database)'
task :drop_schema => :environment do |t,args|
  ActiveRecord::Base.establish_connection
  ActiveRecord::Base.connection.execute("DROP SCHEMA public CASCADE")
  ActiveRecord::Base.connection.execute("CREATE SCHEMA public")
  ActiveRecord::Base.connection.execute("GRANT ALL ON SCHEMA public TO postgres")
  ActiveRecord::Base.connection.execute("GRANT ALL ON SCHEMA public TO public")
  ActiveRecord::Base.connection.execute("COMMENT ON SCHEMA public IS 'standard public schema'")
end

desc 'Recreate the database and seed'
task :redo_db => :environment do |t,args|
  # Executes the dependencies, but only once
  Rake::Task["db:drop_schema"].invoke
  Rake::Task["db:migrate"].invoke
  Rake::Task["db:migrate:status"].invoke 
  Rake::Task["db:structure:dump"].invoke
  Rake::Task["db:seed"].invoke
end

end
jtsagata
fonte
0

Cenário remoto. Mas se você está tentando executar testes em um aplicativo rails e obtém algo como

"ActiveRecord :: StatementInvalid: PG :: ObjectInUse: ERRO: o banco de dados" myapp_test "está sendo acessado por outros usuários DETALHE: Há mais 1 sessão usando o banco de dados."

Certifique-se de fechar o pgAdmin ou qualquer outra ferramenta da GUI do postgres antes de executar os testes.

Shifa Khan
fonte
0

Caso:
falha ao executar a consulta:

DROP TABLE dbo.t_tabelname

Solução:
a. Exiba a Atividade de Status da consulta da seguinte maneira:

SELECT * FROM pg_stat_activity  ;

b. Encontre a linha onde a coluna 'Consulta' contém:

'DROP TABLE dbo.t_tabelname'

c. Na mesma linha, obtenha o valor da coluna 'PID'

example : 16409

d. Execute estes scripts:

SELECT 
    pg_terminate_backend(25263) 
FROM 
    pg_stat_activity 
WHERE 
    -- don't kill my own connection!
    25263 <> pg_backend_pid()
    -- don't kill the connections to other databases
    AND datname = 'database_name'
    ;
Fahwi
fonte
0

Estou em um mac e uso o postgres via Postgres.app. Resolvi esse problema saindo e iniciando novamente o aplicativo.

Juan José Ramírez
fonte
0

Abra o PGadmin para ver se há alguma página de consulta aberta, feche toda a página de consulta e desconecte o servidor PostgresSQL e conecte-o novamente e tente a opção excluir / soltar. Isso me ajudou.

Pritam
fonte
0

No PG admin, você pode desconectar seu servidor (clique com o botão direito no servidor) e todas as sessões serão desconectadas na reinicialização

Alex Binzar
fonte
0

Para mim trabalhou o seguinte:

sudo gitlab-ctl stop
sudo gitlab-ctl start gitaly
sudo gitlab-rake gitlab:setup [type yes and let it finish]
sudo gitlab-ctl start

Estou usando:
gitlab_edition: "gitlab-ce"
gitlab_version: '12 .4.0-ce.0.el7 '

Kostas Demiris
fonte
0

Primeiro, encontre o Postgres que porta sua execução

  1. ps -ef | grep postgres

    seu retornará o número da porta

  2. matar -9 port_number

Por fim, inicie novamente o Postgres

brew services start postgresql 
Poonkodi
fonte