2011-02-24 44 views
232

¿Cómo puedo matar todas mis conexiones postgresql?Mate una sesión/conexión postgresql

Estoy tratando un rake db:drop pero me sale:

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

He intentado cerrar los procesos que veo desde un ps -ef | grep postgres pero esto no funciona bien:

kill: kill 2358 failed: operation not permitted 

Respuesta

430

Usted puede usar pg_terminate_backend() para matar 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, usted tiene que REVOKE privilegios CONNECT para evitar nuevas conexiones:

REVOKE CONNECT ON DATABASE dbname FROM PUBLIC, username; 

If you're using Postgres 8.4-9.1 use procpid instead of 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' 
    ; 
+59

Nótese que en Postgres 9.2, procpid se renombra a pid. – Devin

+7

¡Gracias! Esto se convirtió en una tarea de rake: https://gist.github.com/mfilej/5943114 – mfilej

+0

Si él era un superusuario, ¿no podría haber 'sudo'-ed matar de todos modos? – ndn

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 las mentiras encontradas here y here.

Here's a modified version que funciona tanto para PostgreSQL 9.1 como para 9.2.

4

Tuve este problema y el problema fue que Navicat estaba conectado a mi DB Postgres local. Una vez que desconecté Navicat, el problema desapareció.

EDIT:

Además, as an absolute last resort puede realizar copias de seguridad de sus datos a continuación, ejecute este comando:

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

... que matará a todo lo que el usuario postgres está accediendo. Evite hacer esto en una máquina de producción pero no debería tener un problema con un entorno de desarrollo. Es vital que se asegure de que cadapostgres proceso haya finalizado realmente antes de intentar reiniciar PostgreSQL después de esto.

EDIT 2:

Debido a this unix.SE post he cambiado de kill -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 la conexión ocasional abierta hasta que finaliza la aplicación. – ken

11

OSX, PostgreSQL 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 datadir está en otra parte se puede averiguar dónde está examinando la salida del ps aux | grep postgres

+2

O 'brew services reiniciar postgresql' – PJSCopeland

+0

@PJSCopeland ¡Gracias por la solución más simple! Creo que tu comentario merece ser una respuesta real, así: https://stackoverflow.com/a/48226667/1097104 –

+0

Gracias por eso, @JuusoOhtonen. Sin embargo, le diré lo que quiere decir, si quiere conocer su reputación, ¿podría vincular al menos a mi comentario? – PJSCopeland

6

utilizo la siguiente tarea rastrillo para anular el método Rails drop_database.

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+

+0

Debe usar 'pg_stat_activity.procpid' en lugar de' pg_stat_activity.pid' para Postgres 9.1 y siguientes. Ver http://stackoverflow.com/a/5408501/444774 – talyric

+1

¡Esta es una gran respuesta! Es mejor y más seguro que los Rails predeterminados. ¡Gracias! – piersadrian

146

Tal vez sólo reiniciar postgres =>sudo service postgresql restart

+7

¡respuesta increíble! Seguro y simple – Starkers

+0

@Starkers Fui a través de la mayoría de las respuestas anteriores, hasta que me di cuenta :) –

+14

@Starkers Sí, especialmente seguro en la producción bajo alta carga;) – Erathiel

0

No hay necesidad de caer. 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 
1

Sólo quería señalar que la respuesta de Haris podría no funcionar si algún otro proceso en segundo plano es el uso de la base de datos, en mi caso se retrasó puestos de trabajo, lo hice:

script/delayed_job stop 

Y sólo entonces me fue capaz de colocar/reiniciar la base de datos.

0

Escenario remoto. Pero si intenta ejecutar pruebas en una aplicación de rieles, y obtiene algo como

"ActiveRecord :: StatementInvalid: PG :: ObjectInUse: ERROR: database" myapp_test "está siendo accedido por otros usuarios DETALLE: Allí es 1 sesión más utilizando la base de datos ".

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

-1

caso:
dejará de ejecutar la consulta:

DROP TABLE dbo.t_tabelname 

Solución:
a. Mostrar consulta Estado Actividad de la siguiente manera:

SELECT * FROM pg_stat_activity ; 

b. Encuentre la fila donde la columna 'Query' contiene:

'DROP TABLE dbo.t_tabelname' 

c. En la misma fila, obtenga el valor de 'PID' Columna

example : 16409 

d. Ejecute estos guiones:

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

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

+0

¡Simple y funciona! Para aclarar aún más pgAdmin 4 y reiniciar –

2

he resuelto de esta manera:

En mi Windows8 64 bits, simplemente restart ing del servicio: PostgreSQL-x64-9.5

+1

Eso es solo hacer un reinicio que generalmente no es deseable para entornos de producción, matar el proceso de abrazar es una opción mucho más deseable. – BrianC

12

Con todas las noticias sobre el proceso que se ejecuta:

SELECT *, pg_terminate_backend(pid) 
FROM pg_stat_activity 
WHERE pid <> pg_backend_pid() 
AND datname = 'my_database_name'; 
Cuestiones relacionadas