Programing

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

lottogame 2020. 9. 24. 08:09
반응형

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

연결이 완료되면 애플리케이션이 연결을 종료하도록합니다. PostgreSQL은 연결을 열린 상태로 유지하지 않고 연결을 유지하는 응용 프로그램입니다.


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

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

그런 다음 실행

 rake db:drop

Rails는 데이터베이스에 연결하여 삭제할 가능성이 있지만 phppgadmin을 통해 로그인하면 template1 또는 postgres 데이터베이스를 통해 로그인하므로 영향을받지 않습니다.


드롭하는 ActiveRecord 코드를 간단히 몽키 패치 할 수 있습니다.

Rails 3.x의 경우 :

# lib/tasks/databases.rake
def drop_database(config)
  raise 'Only for Postgres...' unless config['adapter'] == 'postgresql'
  Rake::Task['environment'].invoke
  ActiveRecord::Base.connection.select_all "select pg_terminate_backend(pg_stat_activity.pid) from pg_stat_activity where datname='#{config['database']}' AND state='idle';"
  ActiveRecord::Base.establish_connection config.merge('database' => 'postgres', 'schema_search_path' => 'public')
  ActiveRecord::Base.connection.drop_database config['database']
end

Rails 4.x의 경우 :

# config/initializers/postgresql_database_tasks.rb
module ActiveRecord
  module Tasks
    class PostgreSQLDatabaseTasks
      def drop
        establish_master_connection
        connection.select_all "select pg_terminate_backend(pg_stat_activity.pid) from pg_stat_activity where datname='#{configuration['database']}' AND state='idle';"
        connection.drop_database configuration['database']
      end
    end
  end
end

(from: http://www.krautcomputing.com/blog/2014/01/10/how-to-drop-your-postgres-database-with-rails-4/)


I wrote a gem called pgreset that will automatically kill connections to the database in question when you run rake db:drop (or db:reset, etc). All you have to do is add it to your Gemfile and this issue should go away. At the time of this writing it works with Rails 4 and up and has been tested on Postgres 9.x. Source code is available on github for anyone interested.

gem 'pgreset'

Just make sure that the you have exited the rails console on any open terminal window and exited the rails server...this is one of the most common mistake made by people


I had a similar error saying 1 user was using the database, I realized it was ME! I shut down my rails server and then did the rake:drop command and it worked!


After restarting the server or computer, please try again.

It could be the simple solution.

참고URL : https://stackoverflow.com/questions/2369744/rails-postgres-drop-error-database-is-being-accessed-by-other-users

반응형