Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails + Postgres drop error: database is being accessed by other users

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.

Edit

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?

like image 529
fjuan Avatar asked Mar 03 '10 08:03

fjuan


5 Answers

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.

like image 200
encoded Avatar answered Nov 15 '22 19:11

encoded


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.

like image 20
Mr. Rene Avatar answered Nov 15 '22 19:11

Mr. Rene


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.

like image 17
Jamon Holmgren Avatar answered Nov 15 '22 21:11

Jamon Holmgren


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
like image 12
Chris Aitchison Avatar answered Nov 15 '22 19:11

Chris Aitchison


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

like image 9
Matt Scilipoti Avatar answered Nov 15 '22 20:11

Matt Scilipoti