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

276

Как я могу убить все мои соединения 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
Теги:
database

16 ответов

486
Лучший ответ

Вы можете использовать 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'
    ;

Перед выполнением этого запроса вы должны REVOKE использовать привилегии 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'
    ;
  • 64
    Обратите внимание, что в Postgres 9.2 procpid переименовывается в pid.
  • 7
    Спасибо! Превратил это в грабли: gist.github.com/mfilej/5943114
Показать ещё 4 комментария
179

Возможно, просто перезапустите postgres = > sudo service postgresql restart

  • 9
    удивительный ответ! Безопасно и просто
  • 0
    @ Starkers Я прошел большинство ответов выше, пока меня не осенило :)
Показать ещё 2 комментария
18

Со всей информацией о текущем процессе:

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

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

  • 3
    Или brew services restart postgresql
  • 0
    @PJSCopeland Спасибо за максимально простое решение! Я думаю, что ваш комментарий заслуживает реального ответа, поэтому: stackoverflow.com/a/48226667/1097104
Показать ещё 3 комментария
8

MacOS, если postgresql был установлен с brew:

brew services restart postgresql

Источник: убить сеанс/соединение postgresql

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

Поднятые из gists нашли здесь и здесь.

Здесь изменена версия, которая работает как для PostgreSQL 9.1, так и для 9.2.

6

Я использую следующую команду rake для переопределения метода Rails drop_database.

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+

  • 0
    Вам нужно использовать pg_stat_activity.procpid вместо pg_stat_activity.pid для Postgres 9.1 и ниже. См. Stackoverflow.com/a/5408501/444774
  • 1
    Это отличный ответ! Это лучше и безопаснее, чем по умолчанию в Rails. Спасибо!
4

У меня была эта проблема, и проблема заключалась в том, что Navicat был связан с моей локальной Postgres db. Как только я отключил Navicat, проблема исчезла.

EDIT:

Кроме того, как абсолютное последнее средство, вы можете создать резервную копию своих данных, затем выполнить следующую команду:

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

..., который уничтожит все, к которым обращается пользователь postgres. Избегайте делать это на производственной машине, но у вас не должно быть проблем с средой разработки. Очень важно, чтобы каждый процесс postgres действительно прекратился, прежде чем пытаться перезапустить PostgreSQL после этого.

ИЗМЕНИТЬ 2:

Благодаря этому сообщению unix.SE я изменил с kill -9 на kill -15.

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

Я РЕШИЛ ЭТОТ ПУТЬ:

В моем Windows8 64, просто restart службе: postgresql-x64-9.5

  • 4
    Это просто перезапуск, который, как правило, нежелателен для производственной среды, гораздо более желательным является прекращение процесса объятий.
2

Закройте postgres и перезапустите его. Простой, но работает каждый раз для меня, где другие команды cli иногда этого не делают.

  • 0
    Просто и работает! Чтобы уточнить дальше достаточно pgAdmin 4 и перезапустить
1
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

Просто хотел указать, что Haris Answer может не работать, если какой-либо другой фоновый процесс использует базу данных, в моем случае это были задержки заданий, я сделал:

script/delayed_job stop

И только тогда мне удалось сбросить / reset базу данных.

0

Я на Mac, и я использую postgres через Postgres.app. Я решил эту проблему, просто выйдя и снова запустив приложение.

0

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

"ActiveRecord:: StatementInvalid: PG:: ObjectInUse: ОШИБКА: к базе данных" myapp_test "обращаются другие пользователи ДЕТАЛИ: Существует одна другая сессия, использующая базу данных.

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

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
-1

Дело:
Не удалось выполнить запрос:

DROP TABLE dbo.t_tabelname

Решение:
а. Отобразить запрос Состояние Выполнение действия:

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню