QA@IT

Kill a postgresql session/connection

2694 PV

rake db:drop

Couldn't drop hoge_development : #<ActiveRecord::StatementInvalid: PG::Error: ERROR:  データベース"hoge_development"は他のユーザからアクセスされています
DETAIL:  他にこのデータベースを使っている 1 個のセッションがあります。
: DROP DATABASE IF EXISTS "hoge_development">

のようなエラーで失敗することがありますが、
http://stackoverflow.com/questions/5108876/kill-a-postgresql-session-connection
に解決方法があったのですが、 PostgreSQL 9.2 だと procpidpid になっているのと current_query がなくなっていて、そのままだと動きませんでした。

そこで以下のように変更してみたのですが、 current_query の書き換えがあっているのかどうかわからなくて困っています。

http://www.postgresql.org/docs/9.1/static/monitoring-stats.html
には current_query がどういう値になるのか詳しい情報が無く、 <IDLE> を含むというのがどういう時なのかわかりませんでした。

http://www.postgresql.org/docs/9.2/static/monitoring-stats.html
をみて stateidle のときが同じ状態なのかと思ったのですが、あっているでしょうか?
それとも idle を含む state ( idle in transaction など) も同じ状態なのでしょうか?

それからバージョンチェックももっと良い方法があれば教えてください。

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'))
    if /PostgreSQL (\d+)\.(\d+)/ =~ ActiveRecord::Base.connection.select_all("SELECT version();").first["version"] && ([$1.to_i, $2.to_i] <=> [9, 2]) <= 0
      # 9.2 or later
      proc_pid = "pid"
    else
      # 9.1 or earlier
      proc_pid = "procpid"
    end
    ActiveRecord::Base.connection.select_all("select * from pg_stat_activity order by #{proc_pid};").each do |x|
      if config['database'] == x['datname'] && (x['current_query'] =~ /<IDLE>/ || x['state'] == 'idle')
        ActiveRecord::Base.connection.execute("select pg_terminate_backend(#{x[proc_pid]})")
      end
    end
    ActiveRecord::Base.connection.drop_database config['database']
  end
end
ウォッチ

この質問への回答やコメントをメールでお知らせします。