Beenden Sie eine Postgresql-Sitzung / Verbindung


369

Wie kann ich alle meine Postgresql-Verbindungen beenden?

Ich versuche es, rake db:dropaber ich bekomme:

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

Ich habe versucht, die Prozesse, die ich von a aus sehe, herunterzufahren, ps -ef | grep postgresaber das funktioniert auch nicht:

kill: kill 2358 failed: operation not permitted

Als alle anderen Versuche fehlschlugen, reparierte der pgreset-Edelstein irgendwie die Schienen / pg und dachte, dass eine Verbindung bestand, was nicht der Fall war.
JosephK

Antworten:


671

Sie können pg_terminate_backend () verwenden , um eine Verbindung zu beenden . Sie müssen Superuser sein, um diese Funktion nutzen zu können. Dies funktioniert auf allen Betriebssystemen gleich.

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

Bevor Sie diese Abfrage ausführen, müssen Sie REVOKE die CONNECT - Privilegien , um neue Verbindungen zu vermeiden:

REVOKE CONNECT ON DATABASE dbname FROM PUBLIC, username;

Wenn Sie Postgres 8.4-9.1 verwenden, verwenden Sie procpid anstelle von 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
Beachten Sie, dass in Postgres 9.2 procpid in pid umbenannt wird.
Devin

Wenn er ein Superuser wäre, hätte er sudoden Kill nicht trotzdem machen können?
ndnenkov

3
@ndn Ein Datenbank-Superuser ist nicht dasselbe wie ein Superuser auf Betriebssystemebene. Es gibt keine sudoin PG.
jpmc26

Dies ist die einzige funktionierende Antwort auf viele SO-Fragen, da sie den REVOKESchritt hat. Du hast jemanden gerettet, noch einmal, denke ich!
AymDev

Dies funktioniert danke ....
Ajay Kumar

205

Vielleicht einfach neu starten postgres=>sudo service postgresql restart


@Starkers Ich habe die meisten Antworten oben durchgesehen, bis es mir dämmerte :)
Haris Krajina

32
@Starker Ja, besonders sicher in der Produktion unter hoher Last;)
Erathiel

10
brew services restart postgresqlWenn Sie
gebraut

28

Mit allen Infos zum laufenden Prozess:

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


13

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


Wenn sich Ihr Datenverzeichnis an einer anderen Stelle befindet, können Sie herausfinden, wo es sich befindet, indem Sie die Ausgabe von untersuchen ps aux | grep postgres


4
Oderbrew services restart postgresql
PJSCopeland

@PJSCopeland Danke für die einfachste Lösung! Ich denke, Ihr Kommentar verdient eine echte Antwort, also: stackoverflow.com/a/48226667/1097104
Juuso Ohtonen

Danke dafür, @JuusoOhtonen. Sag dir was, wenn du den Ruf davon haben willst, könntest du zumindest auf meinen Kommentar zurückgreifen?
PJSCopeland

@PJSCopeland Fertig.
Juuso Ohtonen

Hatte Probleme mit anderen Antworten und ähnlichen SO-Post-Lösungen. Laufen Sie pg_ctl restart -D /usr/local/var/postgreshaben den Trick getan! (Ich habe nicht einmal den ersten oder dritten Befehl ausgeführt).
Iggy

8

Dies scheint für PostgreSQL 9.1 zu funktionieren:

#{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

Aufgehoben von den hier und hier gefundenen Kernpunkten .

Hier ist eine modifizierte Version , die sowohl für PostgreSQL 9.1 als auch für 9.2 funktioniert.


6

Ich verwende die folgende Rechenaufgabe, um die Rails- drop_databaseMethode zu überschreiben .

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

Bearbeiten: Dies ist für Postgresql 9.2+


Sie müssen pg_stat_activity.procpidanstelle von pg_stat_activity.pidPostgres 9.1 und niedriger verwenden. Siehe stackoverflow.com/a/5408501/444774
talyric

1
Das ist eine großartige Antwort! Es ist besser und sicherer als die Rails-Standardeinstellung. Vielen Dank!
Piersadrian

5

Einfacher und aktueller ist:

  1. Verwenden Sie ps -ef | grep postgres, um die Verbindungsnummer zu finden
  2. sudo kill -9 "#" der Verbindung

Hinweis: Möglicherweise ist die PID identisch. Wenn man einen tötet, werden alle getötet.


3

Ich hatte dieses Problem und das Problem war, dass Navicat mit meiner lokalen Postgres-Datenbank verbunden war. Nachdem ich Navicat getrennt hatte, verschwand das Problem.

BEARBEITEN:

Auch als absolute Notlösung können Sie Ihre Daten dann führen Sie diesen Befehl sichern:

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

... was alles tötet, auf das der Postgres-Benutzer zugreift. Vermeiden Sie dies auf einer Produktionsmaschine, aber Sie sollten kein Problem mit einer Entwicklungsumgebung haben. Es ist wichtig, dass Sie alle sicherstellen postgres Prozess wirklich beendet wurde, bevor Sie versuchen, PostgreSQL danach neu zu starten.

EDIT 2:

Aufgrund dieses unix.SE-Beitrags habe ich von kill -9zu geändert kill -15.


1
Nach meiner begrenzten Erfahrung mit Navicat Lite reicht es nicht immer aus, nur die Datenbank- oder Serververbindung zu schließen. Navicat Lite scheint die gelegentliche Verbindung offen zu halten, bis die Anwendung beendet wird.
Ken

3

Ich habe diesen Weg gelöst:

In meinem Windows8 64- Bit nur restartden Dienst: postgresql-x64-9.5


5
Dies ist nur ein Neustart, der im Allgemeinen für Produktionsumgebungen nicht wünschenswert ist. Das Beenden des Umarmungsprozesses ist eine viel wünschenswertere Option.
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

Ich wollte nur darauf hinweisen, dass Haris 'Antwort möglicherweise nicht funktioniert, wenn ein anderer Hintergrundprozess die Datenbank verwendet. In meinem Fall handelte es sich um verzögerte Jobs. Ich habe Folgendes getan:

script/delayed_job stop

Und erst dann konnte ich die Datenbank löschen / zurücksetzen.


1

Beenden Sie postgres und starten Sie es neu. Einfach, funktioniert aber jedes Mal bei mir, wo andere CLI-Befehle dies manchmal nicht tun.


Einfach und funktioniert! Zur weiteren Verdeutlichung ganz pgAdmin 4 und Neustart
Ka Tech

0

Es ist nicht nötig, es fallen zu lassen. Löschen Sie einfach das öffentliche Schema und erstellen Sie es neu. In den meisten Fällen hat dies genau den gleichen Effekt.

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

Remote-Szenario. Aber wenn Sie versuchen, Tests in einer Rails-App auszuführen, erhalten Sie so etwas wie

"ActiveRecord :: StatementInvalid: PG :: ObjectInUse: ERROR: Datenbank" myapp_test "wird von anderen Benutzern aufgerufen. DETAIL: Es gibt 1 andere Sitzung, die die Datenbank verwendet."

Stellen Sie sicher, dass Sie pgAdmin oder andere Postgres-GUI-Tools schließen, bevor Sie Tests ausführen.


0

Fall:
Fehler beim Ausführen der Abfrage:

DROP TABLE dbo.t_tabelname

Lösung:
a. Zeigen Sie den Abfragestatus Aktivität wie folgt an:

SELECT * FROM pg_stat_activity  ;

b. Suchen Sie die Zeile, in der die Spalte "Abfrage" Folgendes enthält:

'DROP TABLE dbo.t_tabelname'

c. Erhalten Sie in derselben Zeile den Wert der Spalte 'PID'

example : 16409

d. Führen Sie die folgenden Skripte aus:

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

Ich bin auf einem Mac und benutze Postgres via Postgres.app. Ich habe dieses Problem gelöst, indem ich die App beendet und erneut gestartet habe.


0

Öffnen Sie PGadmin, um festzustellen, ob eine Abfrageseite geöffnet ist, schließen Sie alle Abfrageseiten, trennen Sie den PostgresSQL-Server und verbinden Sie ihn erneut. Versuchen Sie, die Option Löschen / Löschen zu verwenden. Dies hat mir geholfen.


0

In PG admin können Sie Ihren Server trennen (Rechtsklick auf den Server) und alle Sitzungen werden beim Neustart getrennt


0

Für mich hat folgendes funktioniert:

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

Ich benutze:
gitlab_edition: "gitlab-ce"
gitlab_version: '12 .4.0-ce.0.el7 '


0

Suchen Sie zuerst nach Postgres, dessen Port ausgeführt wird

  1. ps -ef | grep postgres

    Es wird die Portnummer zurückgeben

  2. töte -9 port_number

Endlich wieder Postgres starten

brew services start postgresql 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.