3

Is there a way to force a database reset even if Postgres has other users using it. I almost always get this error when I try a $ rake db:reset:

 Couldn't drop example_database_name :
 #<ActiveRecord::StatementInvalid: PG::Error: ERROR:  database "example_database_name" is being accessed by other users DETAIL: 
 There are 2 other session(s) using the database.
4

2 回答 2

5

Put this in a file lib/database.rake if you find yourself using db:reset a lot in development.

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

Obviously only designed for use on non-production databases. It will cause all existing db connections to be severed, so the next page load might be an error if unicorn/passenger/pow is pooling db connections. If this happens, a simple page refresh will cause the server to open a new connection and all will be well.

于 2013-03-31T12:31:41.567 回答
2

if the connected sessions are from your rails process - you definitely want to stop rails, strange things could occur if you drop and rebuild the db from underneath the running process

anyhow the following can be run from the command line to drop postgres connections

psql -c "SELECT pid, pg_terminate_backend(pid) as terminated FROM pg_stat_activity WHERE pid <> pg_backend_pid();" -d 'example_database_name'
于 2013-03-30T18:22:52.520 回答