Mata una sesión / conexión postgresql

371

¿Cómo puedo eliminar todas mis conexiones postgresql?

Estoy intentando un rake db:droppero me sale:

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

Intenté cerrar los procesos que veo desde a ps -ef | grep postgrespero esto tampoco funciona:

kill: kill 2358 failed: operation not permitted
DanS
fuente
Cuando todos los demás intentos fallaron, la gema pgreset de alguna manera arregló rieles / pg pensando que existía una conexión, que no existía.
JosephK

Respuestas:

673

Puede usar pg_terminate_backend () para eliminar una conexión. Tienes que ser superusuario para usar esta función. Esto funciona en todos los sistemas operativos de la misma manera.

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 ejecutar esta consulta, debe REVOCAR los privilegios CONNECT para evitar nuevas conexiones:

REVOKE CONNECT ON DATABASE dbname FROM PUBLIC, username;

Si usa Postgres 8.4-9.1, use procpid en lugar 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
fuente
68
Tenga en cuenta que en Postgres 9.2, procpid cambia su nombre a pid.
Devin
Si fuera un superusuario, ¿no podría haber sudomatado de todas formas?
ndnenkov
3
@ndn Un superusuario de base de datos no es lo mismo que un superusuario de nivel de sistema operativo. No hay sudoen PG.
jpmc26
Esta es la única respuesta que funciona para muchas preguntas SO porque tiene el REVOKEpaso. ¡Salvaste a alguien, una vez más, supongo!
AymDev
Esto funciona gracias ...
Ajay Kumar
205

Tal vez solo reiniciar postgres=>sudo service postgresql restart

Haris Krajina
fuente
@Starkers Revisé la mayoría de las respuestas anteriores, hasta que me di cuenta :)
Haris Krajina
32
@Starkers Sí, especialmente seguro en producción bajo carga alta;)
Erathiel
10
brew services restart postgresqlsi has
preparado
28

Con toda la información sobre el proceso de ejecución:

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

OSX, Postgres 9.2 (instalado con 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


Si su datadir está en otro lugar, puede averiguar dónde está examinando la salida de ps aux | grep postgres

artemave
fuente
44
Obrew services restart postgresql
PJSCopeland
@PJSCopeland ¡Gracias por la solución más simple! Creo que su comentario merece ser una respuesta real, por lo tanto: stackoverflow.com/a/48226667/1097104
Juuso Ohtonen
Gracias por eso, @JuusoOhtonen. Sin embargo, ¿qué le parece si desea obtener la reputación, al menos podría volver a mi comentario?
PJSCopeland
@PJSCopeland Hecho.
Juuso Ohtonen
Tuve problemas con otras respuestas y otras soluciones de publicación SO similares. Ejecutando su pg_ctl restart -D /usr/local/var/postgreshizo el truco! (Ni siquiera ejecuté el primer o tercer comando).
Iggy
8

Esto parece estar funcionando para 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 de lo esencial encontrado aquí y aquí .

Aquí hay una versión modificada que funciona tanto para PostgreSQL 9.1 como para 9.2.

Chris
fuente
6

Utilizo la siguiente tarea de rastrillo para anular el 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

Editar: Esto es para Postgresql 9.2+

Chris Aitchison
fuente
Debe usarlo en pg_stat_activity.procpidlugar de pg_stat_activity.pidPostgres 9.1 y versiones posteriores. Ver stackoverflow.com/a/5408501/444774
talyric
1
¡Esta es una respuesta genial! Es mejor y más seguro que el valor predeterminado de Rails. ¡Gracias!
piersadrian el
5

La forma más fácil y actualizada es:

  1. Use ps -ef | grep postgrespara encontrar la conexión #
  2. sudo kill -9 "#" de la conexión

Nota: Puede haber un PID idéntico. Matar a uno mata a todos.

Señor rene
fuente
3

Tuve este problema y el problema era que Navicat estaba conectado a mi base de datos local de Postgres. Una vez que desconecté Navicat, el problema desapareció.

EDITAR:

Además, como último recurso absoluto, puede hacer una copia de seguridad de sus datos y luego ejecutar este comando:

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

... que matará todo lo que el usuario postgres está accediendo. Evite hacer esto en una máquina de producción, pero no debería tener problemas con un entorno de desarrollo. Es vital que se asegure de que todos los postgres procesos realmente hayan terminado antes de intentar reiniciar PostgreSQL después de esto.

EDITAR 2:

Debido a esta publicación de Unix.SE , he cambiado dekill -9 a kill -15.

Jamon Holmgren
fuente
1
En mi experiencia limitada con Navicat Lite, simplemente cerrar la base de datos o la conexión del servidor no siempre es suficiente. Navicat Lite parece mantener abierta la conexión ocasional hasta que finalice la aplicación.
Ken
3

He resuelto de esta manera:

En mi Windows8 64 bit, solo restarting el servicio: postgresql-x64-9.5

Codificador X
fuente
55
Eso es solo hacer un reinicio que generalmente no es deseable para entornos de producción, matar el proceso de abrazo es una opción mucho más deseable.
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
fuente
1

Solo quería señalar que la respuesta de Haris podría no funcionar si algún otro proceso en segundo plano está utilizando la base de datos, en mi caso fueron trabajos retrasados, lo hice:

script/delayed_job stop

Y solo entonces pude soltar / restablecer la base de datos.

mlabarca
fuente
1

Salga de postgres y reinícielo. Simple, pero siempre funciona para mí, donde otros comandos cli a veces no.

Stan Amsellem
fuente
Simple y funciona! Para aclarar aún más el pgAdmin 4 y reiniciar
Ka Tech
0

No hay necesidad de soltarlo. Simplemente elimine y vuelva a crear el esquema público. En la mayoría de los casos, esto tiene exactamente el mismo efecto.

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
fuente
0

Escenario remoto Pero si está intentando ejecutar pruebas en una aplicación de rieles, y obtiene algo como

"ActiveRecord :: StatementInvalid: PG :: ObjectInUse: ERROR: otros usuarios acceden a la base de datos" myapp_test "DETALLE: Hay otra sesión con la base de datos".

Asegúrese de cerrar pgAdmin o cualquier otra herramienta GUI de postgres antes de ejecutar las pruebas.

Shifa Khan
fuente
0

Caso:
Error al ejecutar la consulta:

DROP TABLE dbo.t_tabelname

Solución:
a. Muestra la actividad de estado de la consulta de la siguiente manera:

SELECT * FROM pg_stat_activity  ;

si. Buscar fila donde la columna 'Consulta' contiene:

'DROP TABLE dbo.t_tabelname'

C. En la misma fila, obtenga el valor de la columna 'PID'

example : 16409

re. Ejecute estos 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
fuente
0

Estoy en una Mac y uso postgres vía Postgres.app. Resolví este problema simplemente saliendo y comenzando de nuevo la aplicación.

Juan José Ramírez
fuente
0

Abra PGadmin para ver si hay alguna página de consulta abierta, cierre todas las páginas de consulta y desconecte el servidor PostgresSQL y conéctelo nuevamente e intente eliminar / soltar. Esto me ayudó.

Pritam
fuente
0

En PG admin puede desconectar su servidor (clic derecho en el servidor) y todas las sesiones se desconectarán al reiniciar

Alex Binzar
fuente
0

Para mí funcionó lo siguiente:

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

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

Kostas Demiris
fuente
0

Primero, encuentre Postgres que puerto está ejecutando

  1. ps -ef | grep postgres

    devolverá el número de puerto

  2. matar -9 port_number

Por fin vuelve a empezar Postgres

brew services start postgresql 
Poonkodi
fuente