[ruby-on-rails] Rails + Postgres 드롭 오류 : 다른 사용자가 데이터베이스에 액세스하고 있습니다.

Postgres를 통해 실행되는 레일 애플리케이션이 있습니다.

두 개의 서버가 있습니다. 하나는 테스트 용이고 다른 하나는 프로덕션 용입니다.

종종 테스트 서버에서 프로덕션 DB를 복제해야합니다.

Vlad를 통해 실행되는 명령은 다음과 같습니다.

rake RAILS_ENV='test_server' db:drop db:create

내가 가진 문제는 다음과 같은 오류가 발생한다는 것입니다.

ActiveRecord::StatementInvalid: PGError: ERROR: database <database_name> is being accessed by other users DROP DATABASE IF EXISTS <database_name>

누군가가 최근에 웹을 통해 애플리케이션에 액세스 한 경우 발생합니다 (postgres는 “세션”을 열어 둡니다).

postgres DB에서 세션을 종료 할 수있는 방법이 있습니까?

감사합니다.

편집하다

phppgadmin의 인터페이스를 사용하여 데이터베이스를 삭제할 수 있지만 rake 작업으로는 삭제할 수 없습니다.

레이크 작업으로 phppgadmin의 드롭을 복제하려면 어떻게해야합니까?



답변

애플리케이션에 대해 실행중인 postgresql 연결을 종료하면 db : drop을 잘 실행할 수 있습니다. 그렇다면 연결을 끊는 방법은 무엇입니까? 다음 레이크 작업을 사용합니다.

# 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

언더 레일에서 연결을 끊으면 다음에 페이지를로드하려고 할 때 오류가 발생하지만 다시로드하면 연결이 다시 설정됩니다.


답변

더 쉽고 업데이트 된 방법은 다음과 같습니다. 1. ps -ef | grep postgres연결 # 2.을 찾는 데 사용 합니다.sudo kill -9 "# of the connection

참고 : 동일한 PID가있을 수 있습니다. 하나를 죽이면 모두 죽습니다.


답변

다음은 postgres 데이터베이스에 대한 모든 연결을 끊는 빠른 방법입니다.

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

경고 : 이렇게하면 postgres사용자가 연 실행중인 모든 프로세스가 종료 되므로 먼저이 작업을 수행할지 확인하십시오.


답변

위의 “kill processes”방법을 사용했을 때 db : drop이 실패했습니다 (: kill_postgres_connections가 전제 조건 인 경우). rake 명령이 사용하는 연결이 끊어 졌기 때문이라고 생각합니다. 대신 sql 명령을 사용하여 연결을 끊습니다. 이것은 db : drop의 전제 조건으로 작동하고 다소 복잡한 명령을 통해 프로세스를 종료 할 위험을 방지하며 모든 OS에서 작동해야합니다 (gentoo는에 대해 다른 구문이 필요함 kill).

cmd = %(psql -c "SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE procpid <> pg_backend_pid();" -d '#{db_name}')

다음은 database.yml에서 데이터베이스 이름을 읽고 개선 된 (IMHO) 명령을 실행하는 레이크 작업입니다. 또한 db : drop의 전제 조건으로 db : kill_postgres_connections를 추가합니다. 레일을 업그레이드 한 후에는이 패치가 더 이상 필요하지 않을 수 있음을 알리는 경고가 포함됩니다.

참조 : https://gist.github.com/4455341 , 참조 포함


답변

다음 레이크 작업을 사용하여 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


답변

Rails 콘솔 또는 서버가 다른 탭에서 실행 중인지 확인한 다음

레일 서버와 콘솔을 중지하십시오.

그런 다음 실행

 rake db:drop


답변

연결이 완료되면 애플리케이션이 연결을 종료하도록합니다. PostgreSQL은 연결을 유지하지 않고 연결을 유지하는 애플리케이션입니다.