Вбийте сеанс / з'єднання postgresql


369

Як я можу вбити всі мої з'єднання postgresql?

Я намагаюся, rake db:dropале я отримую:

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

Я намагався вимкнути процеси, які я бачу, ps -ef | grep postgresале це також не працює:

kill: kill 2358 failed: operation not permitted

Коли всі інші спроби не вдалися, дорогоцінний камінь pgreset якось зафіксував рейки / pg, думаючи, що існувало з'єднання, чого не було.
JosephK

Відповіді:


671

Ви можете використовувати pg_terminate_backend (), щоб перервати з'єднання. Щоб користуватися цією функцією, ви повинні бути суперкористувачем. Це працює у всіх операційних системах однаково.

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

Перш ніж виконати цей запит, вам потрібно відхилити права доступу CONNECT, щоб уникнути нових з'єднань:

REVOKE CONNECT ON DATABASE dbname FROM PUBLIC, username;

Якщо ви використовуєте Postgres 8.4-9.1, використовуйте propid замість 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
Зауважте, що в Postgres 9.2, пропіден перейменований у pid.
Девін

Якби він був надрукувальником, чи не міг він sudoвсе-таки вбити убивство?
ndnenkov

3
@ndn Суперрусер бази даних - це не те саме, що суперусер рівня ОС. У sudoПГ немає .
jpmc26

Це єдина діюча відповідь на багато питань ТА, оскільки вона має REVOKEкрок. Ви врятували когось, я ще раз здогадуюсь!
AymDev

Це працює спасибі ....
Аджай Кумар

205

Можливо, просто перезавантажте postgres=>sudo service postgresql restart


@Starkers Я переглянув більшість відповідей вище, поки це не зійшло на мені :)
Харіс Крайна

32
@Starkers Так, особливо безпечний у виробництві під великим навантаженням;)
Ератьєль

10
brew services restart postgresqlякщо у вас заварюють
Сем Ках Чін

28

З усіма відомостями про запущений процес:

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


13

OSX, Postgres 9.2 (встановлено з домашньою мовою)

$ 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


Якщо ваш datadir знаходиться в іншому місці, ви можете дізнатися, де він знаходиться, вивчивши вихідний результат ps aux | grep postgres


4
Абоbrew services restart postgresql
PJSCopeland

@PJSCopeland Дякую за максимально просте рішення! Я думаю , що ваш коментар заслуговує того, щоб бути реальний відповідь, таким чином: stackoverflow.com/a/48226667/1097104
Juuso Ohtonen

Дякую за це, @JuusoOhtonen. Скажу вам, що хоч, якщо ви хочете, щоб репутація від нього, ви могли хоч би посилання на мій коментар?
PJSCopeland

@PJSCopeland Готово.
Juuso Ohtonen

У вас виникли проблеми з іншими відповідями та іншими подібними рішеннями SO. Запуск вашого pg_ctl restart -D /usr/local/var/postgresзробив свою справу! (Я навіть не виконував першої чи третьої команди).
Іггі

8

Схоже, це працює для 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

Піднятий з сутків, знайдених тут і тут .

Ось змінена версія, яка працює як для PostgreSQL 9.1, так і 9.2.


6

Я використовую наступне завдання граблі, щоб замінити drop_databaseметод 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

Редагувати: це для Postgresql 9.2+


Вам потрібно використовувати pg_stat_activity.procpidзамість pg_stat_activity.pidPostgres 9.1 і нижче. Див stackoverflow.com/a/5408501/444774
talyric

1
Це чудова відповідь! Це краще і безпечніше за замовчуванням Rails. Дякую!
пристань

5

Простіший і оновлений спосіб:

  1. Використовуйте ps -ef | grep postgresдля пошуку з'єднання №
  2. sudo kill -9 "#" з'єднання

Примітка: може бути однаковий PID. Вбивство одного вбиває всіх.


3

У мене виникло це питання, і проблема полягала в тому, що Navicat був підключений до мого місцевого поштового зв’язку Postgres. Як тільки я відключив Navicat, проблема зникла.

Редагувати:

Крім того , як абсолютні крайній випадок ви можете створити резервну копію ваших даних , то виконайте наступну команду:

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

... що знищить усе, до чого користувач postgres отримує доступ. Уникайте цього робити на виробничій машині, але у вас не повинно виникнути проблем із середовищем розробки. Важливо, щоб ви забезпечували кожного postgres процес справді закінчується перед спробою перезапустити PostgreSQL після цього.

EDIT 2:

Завдяки цій публікації на unix.SE я змінився з kill -9на kill -15.


1
З мого обмеженого досвіду роботи з Navicat Lite, просто закрити базу даних або підключення до сервера не завжди достатньо. Navicat Lite, здається, підтримує відкрите час від часу підключення до завершення роботи програми.
кен

3

Я вирішив цей спосіб:

У моєму 64- розрядному Windows8 , лише користуючисьrestart сервісом: postgresql-x64-9.5


5
Це просто перезапуск, який, як правило, не бажаний для виробничих умов, вбивчий процес обіймів є набагато більш бажаним варіантом.
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

Я просто хотів зазначити, що відповідь Харіса може не спрацювати, якщо якийсь інший фоновий процес використовує базу даних, у моєму випадку це були затримки роботи, я зробив:

script/delayed_job stop

І лише тоді мені вдалося скинути / скинути базу даних.


1

Закрийте postgres і перезавантажте його. Простий, але працює для мене щоразу, де інші команди cli іноді не роблять.


Просто і працює! Щоб уточнити далі, досить pgAdmin 4 та перезапустіть
Ka Tech

0

Не потрібно його скидати. Просто видаліть і відтворіть загальнодоступну схему. У більшості випадків це має точно такий же ефект.

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

Віддалений сценарій. Але якщо ви намагаєтеся запустити тести в додатку рейкові, і ви отримаєте щось подібне

"ActiveRecord :: StatementInvalid: PG :: ObjectInUse: ПОМИЛКА: база даних" myapp_test "доступна іншим користувачам ДЕТАЛЬНО: Є ще один сеанс використання бази даних."

Перед запуском тестів переконайтесь, що ви закрили pgAdmin або будь-які інші інструменти графічного інтерфейсу Postgres.


0

Випадок:
Не вдалося виконати запит:

DROP TABLE dbo.t_tabelname

Рішення:
а. Показати активність статусу запиту таким чином:

SELECT * FROM pg_stat_activity  ;

б. Знайдіть рядок, де стовпець "Запит" містить:

'DROP TABLE dbo.t_tabelname'

c. У цьому ж рядку отримайте значення стовпця "PID"

example : 16409

г. Виконайте ці сценарії:

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

Я на Mac і використовую postgres via Postgres.app. Я вирішив цю проблему, просто закривши програму та запустивши її знову.


0

Відкрийте PGadmin, перевірте, чи відкрита будь-яка сторінка запитів, закрийте всю сторінку запиту та відключіть сервер PostgresSQL та підключіть його ще раз та спробуйте вилучити / випустити варіант. Це мені допомогло.


0

У адміністратора PG ви можете відключити ваш сервер (клацніть правою кнопкою миші на сервері), і всі сеанси будуть відключені при перезапуску


0

Для мене працювали наступні:

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

Я використовую:
gitlab_edition: "gitlab-ce"
gitlab_version: '12 .4.0-ce.0.el7 '


0

Спочатку знайдіть Postgres, який порту працює

  1. ps -ef | grep postgres

    він поверне номер порту

  2. вбити -9 port_number

Нарешті знову запустіть Postgres

brew services start postgresql 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.