I have a rails application running over Postgres.
I have two servers: one for testing and the other for production.
Very often I need to clone the production DB on the test server.
The command I'm runnig via Vlad is:
rake RAILS_ENV='test_server' db:drop db:create
The problem I'm having is that I receive the following error:
ActiveRecord::StatementInvalid: PGError: ERROR: database <database_name> is being accessed by other users DROP DATABASE IF EXISTS <database_name>
This happens if someone has accessed the application via web recently (postgres keeps a "session" opened)
Is there any way that I can terminate the sessions on the postgres DB?
Thank you.
I can delete the database using phppgadmin's interface but not with the rake task.
How can I replicate phppgadmin's drop with a rake task?
If you kill the running postgresql connections for your application, you can then run db:drop just fine. So how to kill those connections? I use the following rake task:
# lib/tasks/kill_postgres_connections.rake
task :kill_postgres_connections => :environment do
  db_name = "#{File.basename(Rails.root)}_#{Rails.env}"
  sh = <<EOF
ps xa \
  | grep postgres: \
  | grep #{db_name} \
  | grep -v grep \
  | awk '{print $1}' \
  | xargs kill
EOF
  puts `#{sh}`
end
task "db:drop" => :kill_postgres_connections
Killing the connections out from under rails will sometimes cause it to barf the next time you try to load a page, but reloading it again re-establishes the connection.
Easier and more updated way is:
1. Use ps -ef | grep postgres to find the connection #
2. sudo kill -9 "# of the connection
Note: There may be identical PID. Killing one kills all.
Here's a quick way to kill all the connections to your postgres database.
sudo kill -9 `ps -u postgres -o pid` 
Warning: this will kill any running processes that the postgres user has open, so make sure you want to do this first.
I use the following rake task to override the Rails drop_database method.
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
                        When we used the "kill processes" method from above, the db:drop was failing (if :kill_postgres_connections was prerequisite).  I believe it was because the connection which that rake command was using was being killed. Instead, we are using a sql command to drop the connection.  This works as a prerequisite for db:drop, avoids the risk of killing processes via a rather complex command, and it should work on any OS (gentoo required different syntax for kill).
cmd = %(psql -c "SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE procpid <> pg_backend_pid();" -d '#{db_name}')
Here is a rake task that reads the database name from database.yml and runs an improved (IMHO) command. It also adds db:kill_postgres_connections as a prerequisite to db:drop. It includes a warning that yells after you upgrade rails, indicating that this patch may no longer be needed.
see: https://gist.github.com/4455341, references included
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With