Убить сеанс / соединение postgresql


371

Как я могу убить все мои соединения 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 каким-то образом исправил rails / pg, думая, что соединение существует, чего не было.
JosephK

Ответы:


673

Вы можете использовать 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, используйте procpid вместо 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 procpid переименовывается в pid.
Девин

Если бы он был суперпользователем, разве он не мог sudoубить?
ndnenkov

3
@ndn Суперпользователь базы данных - это не то же самое, что суперпользователь уровня ОС. Нет sudoв пг.
jpmc26

Это единственный рабочий ответ на многие вопросы SO, потому что у него есть REVOKEшаг. Вы спасли кого-то, я думаю, еще раз!
АймДев

Это работает, спасибо ....
Аджай Кумар

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 (устанавливается вместе с 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


Если ваш датадир находится в другом месте, вы можете узнать, где он находится, изучив вывод ps aux | grep postgres


4
Илиbrew services restart postgresql
ПАОПеланд

@PJSCopeland Спасибо за самое простое решение! Я думаю, что ваш комментарий заслуживает того, чтобы быть реальным ответом, поэтому: stackoverflow.com/a/48226667/1097104
Юусо Охтонен

Спасибо за это, @JuusoOhtonen. Скажи, что, хотя, если ты хочешь получить репутацию от нее, ты мог бы по крайней мере дать ссылку на мой комментарий?
ПАОПеланд

@PJSCopeland Готово.
Юусо Охтонен

Были проблемы с другими ответами и другими подобными 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

Я использую следующую задачу rake, чтобы переопределить 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. Спасибо!
piersadrian

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 после этого.

РЕДАКТИРОВАТЬ 2:

Из-за этого поста unix.SE я изменил с kill -9на kill -15.


1
Из-за моего ограниченного опыта работы с Navicat Lite простого закрытия базы данных или соединения с сервером не всегда достаточно. Кажется, что Navicat Lite сохраняет время от времени соединение открытым, пока приложение не будет прервано.
Кен

3

Я решил это

В моей Windows 8 64- битной 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

Удаленный сценарий. Но если вы пытаетесь запустить тесты в приложении rails, и вы получаете что-то вроде

«ActiveRecord :: StatementInvalid: PG :: ObjectInUse: ОШИБКА: база данных« myapp_test »используется другими пользователями. ПОДРОБНЕЕ: Есть еще 1 сеанс, использующий базу данных».

Убедитесь, что вы закрыли pgAdmin или любые другие инструменты GUI postgres перед запуском тестов.


0

Случай:
не удалось выполнить запрос:

DROP TABLE dbo.t_tabelname

Решение:
а. Отобразить запрос Status Activity следующим образом:

SELECT * FROM pg_stat_activity  ;

б. Найти строку, в которой столбец «Запрос» содержит:

'DROP TABLE dbo.t_tabelname'

с. В той же строке получить значение столбца '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

Откройте PGadmin, посмотрите, открыта ли какая-либо страница запросов, закройте все страницы запросов, отключите сервер PostgresSQL, снова подключите его и попробуйте удалить / удалить. Это помогло мне.


0

В PG admin вы можете отключить ваш сервер (щелкнуть правой кнопкой мыши на сервере) и все сессии будут отключены при перезапуске


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.