Uccidi una sessione / connessione postgresql


371

Come posso uccidere tutte le mie connessioni postgresql?

Sto provando un rake db:dropma ottengo:

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

Ho provato a chiudere i processi che vedo da un ps -ef | grep postgresma questo non funziona neanche:

kill: kill 2358 failed: operation not permitted

Quando tutti gli altri tentativi fallirono, la gemma di pgreset in qualche modo risolveva rotaie / pg pensando che esistesse una connessione, che non lo fece.
JosephK,

Risposte:


673

È possibile utilizzare pg_terminate_backend () per interrompere una connessione. Devi essere un superutente per utilizzare questa funzione. Funziona allo stesso modo su tutti i sistemi operativi.

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

Prima di eseguire questa query, è necessario revocare i privilegi CONNECT per evitare nuove connessioni:

REVOKE CONNECT ON DATABASE dbname FROM PUBLIC, username;

Se stai usando Postgres 8.4-9.1 usa procpid invece di 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
Si noti che in Postgres 9.2, procpid viene rinominato in pid.
Devin,

Se fosse un superutente, non avrebbe potuto sudocomunque uccidere?
ndnenkov,

3
@ndn Un superutente del database non è la stessa cosa di un superutente a livello di sistema operativo. Non c'è sudoin PG.
jpmc26,

Questa è l'unica risposta funzionante per molte domande SO perché ha il REVOKEpasso. Hai salvato qualcuno, un'altra volta immagino!
AymDev,

Questo funziona grazie ....
Ajay Kumar il

205

Forse basta riavviare postgres=>sudo service postgresql restart


@Starkers Ho esaminato la maggior parte delle risposte sopra, fino a quando non mi sono reso conto :)
Haris Krajina,

32
@Starkers Sì, particolarmente sicuro nella produzione sotto carico elevato;)
Erathiel

10
brew services restart postgresqlse hai
preparato la

28

Con tutte le informazioni sul processo in esecuzione:

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


13

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


Se il tuo datadir è altrove, puoi scoprire dove si trova esaminando l'output di ps aux | grep postgres


4
Oppurebrew services restart postgresql
PJSCopeland,

@PJSCopeland Grazie per la soluzione estremamente semplice! Credo che il tuo commento merita di essere una vera risposta, in tal modo: stackoverflow.com/a/48226667/1097104
Juuso Ohtonen

Grazie per quello, @JuusoOhtonen. Ti dico cosa, però, se vuoi la reputazione da esso, potresti almeno ricollegarti al mio commento?
PJSCopeland

@PJSCopeland Done.
Juuso Ohtonen,

Ha avuto problemi con altre risposte e altre soluzioni simili di post SO. In esecuzione il tuo ha pg_ctl restart -D /usr/local/var/postgresfatto il trucco! (Non ho nemmeno eseguito il primo o il terzo comando).
Iggy,

8

Questo sembra funzionare per 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

Sollevato dagli spiriti trovati qui e qui .

Ecco una versione modificata che funziona con PostgreSQL 9.1 e 9.2.


6

Uso la seguente attività di rake per sovrascrivere il drop_databasemetodo 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

Modifica: questo è per Postgresql 9.2+


Devi usare pg_stat_activity.procpidinvece che pg_stat_activity.pidper Postgres 9.1 e precedenti. Vedere stackoverflow.com/a/5408501/444774
talyric

1
Questa è un'ottima risposta! È migliore e più sicuro rispetto all'impostazione predefinita di Rails. Grazie!
piersadrian,

5

Il modo più semplice e aggiornato è:

  1. Utilizzare ps -ef | grep postgresper trovare la connessione #
  2. sudo kill -9 "#" della connessione

Nota: potrebbe esserci un PID identico. Uccidere uno uccide tutto.


3

Ho avuto questo problema e il problema era che Navicat era collegato al mio db Postgres locale. Dopo aver disconnesso Navicat il problema è scomparso.

MODIFICARE:

Inoltre, come ultima risorsa assoluta è possibile eseguire il backup dei dati quindi eseguire questo comando:

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

... che ucciderà tutto ciò a cui accede l'utente postgres. Evita di farlo su una macchina di produzione ma non dovresti avere problemi con un ambiente di sviluppo. È fondamentale che tu assicuri tutto postgres processo sia terminato davvero prima di tentare di riavviare PostgreSQL dopo questo.

EDIT 2:

A causa di questo post unix.SE ho cambiato da kill -9a kill -15.


1
Nella mia esperienza limitata con Navicat Lite, chiudere semplicemente la connessione al database o al server non è sempre sufficiente. Navicat Lite sembra mantenere aperta la connessione occasionale fino al termine dell'applicazione.
Ken,

3

HO RISOLTO IN QUESTO MODO:

Nel mio Windows8 64 bit, solo restartil servizio: postgresql-x64-9.5


5
Questo è solo un riavvio che generalmente non è desiderabile per gli ambienti di produzione, uccidere il processo di abbraccio è un'opzione molto più desiderabile.
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

Volevo solo sottolineare che la risposta di Haris potrebbe non funzionare se qualche altro processo in background utilizza il database, nel mio caso si trattava di lavori ritardati, ho fatto:

script/delayed_job stop

E solo allora sono stato in grado di eliminare / ripristinare il database.


1

Esci da postgres e riavvialo. Semplice, ma funziona sempre per me, dove altri comandi cli a volte no.


Semplice e funziona! Per chiarire ulteriormente abbastanza pgAdmin 4 e riavviare
Ka Tech

0

Non è necessario rilasciarlo. Basta eliminare e ricreare lo schema pubblico. Nella maggior parte dei casi questo ha esattamente lo stesso effetto.

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

Scenario remoto Ma se stai provando a eseguire test in un'app di binari e ottieni qualcosa di simile

"ActiveRecord :: StatementInvalid: PG :: ObjectInUse: ERROR: il database" myapp_test "è accessibile da altri utenti DETTAGLIO: C'è un'altra sessione utilizzando il database."

Assicurati di chiudere pgAdmin o altri strumenti della GUI di postgres prima di eseguire i test.


0

Astuccio :
impossibile eseguire la query:

DROP TABLE dbo.t_tabelname

Soluzione:
a. Visualizza l'attività di stato della query come segue:

SELECT * FROM pg_stat_activity  ;

b. Trova la riga in cui la colonna "Query" contiene:

'DROP TABLE dbo.t_tabelname'

c. Nella stessa riga, ottieni il valore della colonna "PID"

example : 16409

d. Eseguire questi script:

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

Sono su un Mac e utilizzo Postgres via Postgres.app. Ho risolto questo problema semplicemente uscendo e ricominciando l'app.


0

Apri PGadmin per vedere se c'è qualche pagina di query aperta, chiudi tutta la pagina di query e disconnetti il ​​server PostgresSQL e ricollegalo e prova a eliminare / rilasciare l'opzione. Questo mi ha aiutato.


0

In PG admin puoi disconnettere il tuo server (tasto destro sul server) e tutte le sessioni verranno disconnesse al riavvio


0

Per me ha funzionato come segue:

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

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


0

Per prima cosa, trova Postgres che porta il suo funzionamento

  1. ps -ef | grep postgres

    restituirà il numero di porta

  2. uccidere -9 port_number

Alla fine ricominciare Postgres

brew services start postgresql 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.