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

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'
    ;

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


@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';


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


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.


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+


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.


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.


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


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

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.


1

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


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

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.


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'
    ;

0

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


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ó.


0

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


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 '


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 
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.