Zabij sesję / połączenie postgresql

369

Jak mogę zabić wszystkie moje połączenia Postgresql?

Próbuję, rake db:dropale dostaję:

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

Próbowałem zamknąć procesy, które widzę z, ps -ef | grep postgresale to też nie działa:

kill: kill 2358 failed: operation not permitted
DanS
źródło
Kiedy wszystkie inne próby nie powiodły się, klejnot pgreset w jakiś sposób naprawił szyny / pg, myśląc, że istniało połączenie, ale nie.
JosephK

Odpowiedzi:

671

Możesz użyć pg_terminate_backend (), aby zabić połączenie. Aby korzystać z tej funkcji, musisz być superużytkownikiem. Działa to we wszystkich systemach operacyjnych tak samo.

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

Przed wykonaniem tego zapytania musisz cofnąć uprawnienia CONNECT, aby uniknąć nowych połączeń:

REVOKE CONNECT ON DATABASE dbname FROM PUBLIC, username;

Jeśli używasz Postgres 8.4-9.1, użyj procpid zamiast 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
źródło
68
Zauważ, że w Postgres 9.2 nazwa procpid została zmieniona na pid.
Devin,
Jeśli był superużytkownikiem, czy i tak nie byłby w stanie sudozabić?
ndnenkov
3
@ndn Superuser bazy danych to nie to samo, co superużytkownik na poziomie systemu operacyjnego. Nie ma sudow PG.
jpmc26,
Jest to jedyna działająca odpowiedź na wiele pytań SO, ponieważ ma jeden REVOKEkrok. Uratowałeś kogoś, chyba jeszcze raz!
AymDev
To działa dzięki ...
Ajay Kumar
205

Może po prostu uruchom ponownie postgres=>sudo service postgresql restart

Haris Krajina
źródło
@Starkers Przeszedłem większość odpowiedzi powyżej, aż do mnie dotarło :)
Haris Krajina
32
@Starkers Tak, szczególnie bezpieczny w produkcji pod dużym obciążeniem;)
Erathiel,
10
brew services restart postgresqljeśli masz napar
Sam Kah Chiin
28

Wszystkie informacje o trwającym procesie:

SELECT *, pg_terminate_backend(pid)
FROM pg_stat_activity 
WHERE pid <> pg_backend_pid()
AND datname = 'my_database_name';
dorycki
źródło
13

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


Jeśli twój katalog danych znajduje się gdzie indziej, możesz dowiedzieć się, gdzie on jest, sprawdzając dane wyjściowe ps aux | grep postgres

artemave
źródło
4
Lubbrew services restart postgresql
PJSCopeland
@PJSCopeland Dzięki za bardzo proste rozwiązanie! Myślę, że twój komentarz zasługuje na prawdziwą odpowiedź, a zatem: stackoverflow.com/a/48226667/1097104
Juuso Ohtonen
Dzięki za to, @JuusoOhtonen. Powiem ci jednak, jeśli chcesz od tego reputacji, możesz przynajmniej link do mojego komentarza?
PJSCopeland
@PJSCopeland Gotowe.
Juuso Ohtonen,
Miałem problemy z innymi odpowiedziami i innymi podobnymi rozwiązaniami SO post. Uruchamianie pg_ctl restart -D /usr/local/var/postgreszałatwiło sprawę! (Nie uruchomiłem nawet pierwszego ani trzeciego polecenia).
Iggy
8

Wydaje się, że działa to dla 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

Zniesione z istoty znalezionej tu i tutaj .

Oto zmodyfikowana wersja, która działa zarówno dla PostgreSQL 9.1, jak i 9.2.

Chris
źródło
6

Korzystam z następującego zadania prowizji, aby zastąpić drop_databasemetodę 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

Edycja: dotyczy Postgresql 9.2+

Chris Aitchison
źródło
Musisz użyć pg_stat_activity.procpidzamiast pg_stat_activity.pidPostgres 9.1 i niższych. Zobacz stackoverflow.com/a/5408501/444774
talyric
1
To świetna odpowiedź! Jest lepszy i bezpieczniejszy niż domyślny Rails. Dzięki!
piersadrian
5

Łatwiejszym i bardziej aktualnym sposobem jest:

  1. Użyj, ps -ef | grep postgresaby znaleźć połączenie #
  2. sudo kill -9 "#" połączenia

Uwaga: Może istnieć identyczny PID. Zabicie jednego zabija wszystkich.

Pan Rene
źródło
3

Miałem ten problem i problem polegał na tym, że Navicat był podłączony do mojej lokalnej bazy danych Postgres. Po odłączeniu Navicat problem zniknął.

EDYTOWAĆ:

Ponadto jako ostateczność można wykonać kopię zapasową danych, a następnie uruchomić polecenie:

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

... co zabije wszystko, do czego użytkownik postgres ma dostęp. Unikaj robienia tego na maszynie produkcyjnej, ale nie powinieneś mieć problemu ze środowiskiem programistycznym. Ważne jest, aby upewnić się, że każdy postgres proces naprawdę się zakończył, zanim spróbujesz ponownie uruchomić PostgreSQL.

EDYCJA 2:

Ze względu na ten post unix.SE zmieniłem z kill -9na kill -15.

Jamon Holmgren
źródło
1
Według mojego ograniczonego doświadczenia z Navicat Lite, samo zamknięcie bazy danych lub połączenia z serwerem nie zawsze wystarcza. Navicat Lite wydaje się utrzymywać sporadyczne połączenie otwarte, dopóki aplikacja nie zostanie zakończona.
Ken
3

Rozwiązałem ten sposób:

W moim 64 -bitowym systemie Windows 8 po prostu restartusługa: postgresql-x64-9.5

X-Coder
źródło
5
To po prostu restart, który na ogół nie jest pożądany w środowiskach produkcyjnych, zabicie procesu przytulania jest znacznie bardziej pożądaną opcją.
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
źródło
1

Chciałem tylko zaznaczyć, że odpowiedź Harisa może nie działać, jeśli z bazy danych korzysta inny proces działający w tle, w moim przypadku były to zadania opóźnione:

script/delayed_job stop

I dopiero wtedy mogłem upuścić / zresetować bazę danych.

Mlabarca
źródło
1

Zamknij postgres i uruchom go ponownie. Proste, ale działa za każdym razem dla mnie, gdzie czasami inne polecenia CLI nie działają.

Stan Amsellem
źródło
Proste i działa! Aby wyjaśnić więcej, pgAdmin 4 i uruchom ponownie
Ka Tech
0

Nie trzeba go upuszczać. Wystarczy usunąć i ponownie utworzyć schemat publiczny. W większości przypadków ma to dokładnie taki sam efekt.

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
źródło
0

Scenariusz zdalny. Ale jeśli próbujesz uruchomić testy w aplikacji railsowej, a otrzymasz coś takiego

„ActiveRecord :: StatementInvalid: PG :: ObjectInUse: ERROR: baza danych„ test_aplikacji ”jest uzyskiwany przez innych użytkowników SZCZEGÓŁ: Z bazy danych korzysta 1 inna sesja.”

Upewnij się, że zamknąłeś pgAdmin lub inne narzędzia GUI postgres przed uruchomieniem testów.

Shifa Khan
źródło
0

Przypadek:
Nie można wykonać zapytania:

DROP TABLE dbo.t_tabelname

Rozwiązanie:
a. Wyświetl zapytanie Status Aktywność w następujący sposób:

SELECT * FROM pg_stat_activity  ;

b. Znajdź wiersz, w którym znajduje się kolumna „Zapytanie”:

'DROP TABLE dbo.t_tabelname'

do. W tym samym wierszu uzyskaj wartość kolumny „PID”

example : 16409

re. Uruchom następujące skrypty:

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
źródło
0

Jestem na komputerze Mac i korzystam z Postgres przez Postgres.app. Rozwiązałem ten problem po prostu zamykając i uruchamiając ponownie aplikację.

Juan José Ramírez
źródło
0

Otwórz PGadmin, aby sprawdzić, czy jest otwarta strona zapytania, zamknij wszystkie strony zapytania i odłącz serwer PostgresSQL, a następnie podłącz go ponownie i spróbuj usunąć / upuścić. Pomogło mi to.

Pritam
źródło
0

W PG admin możesz rozłączyć serwer (kliknij prawym przyciskiem myszy na serwerze), a wszystkie sesje zostaną rozłączone przy ponownym uruchomieniu

Alex Binzar
źródło
0

Dla mnie zadziałało:

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

Używam:
gitlab_edition: "gitlab-ce"
gitlab_version: '12 .4.0-ce.0.el7 '

Kostas Demiris
źródło
0

Najpierw znajdź Postgres, który port działa

  1. ps -ef | grep postgres

    zwróci numer portu

  2. zabij -9 port_number

W końcu ponownie uruchom Postgres

brew services start postgresql 
Poonkodi
źródło