रेल + पोस्ट ड्रॉप त्रुटि: डेटाबेस को अन्य उपयोगकर्ताओं द्वारा एक्सेस किया जा रहा है


90

मैं एक रेल अनुप्रयोग Postgres पर चल रहा है।

मेरे पास दो सर्वर हैं: एक परीक्षण के लिए और दूसरा उत्पादन के लिए।

बहुत बार मुझे परीक्षण सर्वर पर उत्पादन डीबी को क्लोन करने की आवश्यकता होती है।

व्लाद के माध्यम से मैं चल रहा हूँ कमांड है:

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>

ऐसा तब होता है जब किसी ने हाल ही में वेब के माध्यम से एप्लिकेशन एक्सेस किया है (पोस्टग्रेज एक "सत्र खोलकर रखता है")

क्या कोई तरीका है कि मैं पोस्टग्रैब्स डीबी पर सत्र समाप्त कर सकता हूं?

धन्यवाद।

संपादित करें

मैं phpgadmin के इंटरफ़ेस का उपयोग करके डेटाबेस को हटा सकता हूं लेकिन रेक कार्य के साथ नहीं।

मैं फेकगैडमिन की ड्रॉप को एक रेक कार्य के साथ कैसे दोहरा सकता हूं?


सुनिश्चित करें कि आपके पास डेटाबेस से कनेक्शन नहीं है या यह इसे नहीं छोड़ेगा। इसके बारे में यहां और देखें
नशा जोरिक

जवाबों:


81

यदि आप अपने आवेदन के लिए रनिंग पोस्टग्रैसकल कनेक्शन को मारते हैं, तो आप डीबी चला सकते हैं: बस ठीक छोड़ दें। तो उन कनेक्शनों को कैसे मारें? मैं निम्नलिखित रेक कार्य का उपयोग करता हूं:

# 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

अगली बार जब आप किसी पृष्ठ को लोड करने का प्रयास करते हैं, तो रेल के नीचे से कनेक्शन को मारना कभी-कभी इसे रोक सकता है, लेकिन इसे फिर से लोड करने से कनेक्शन फिर से स्थापित हो जाता है।


2
मुझे sudo को xargs में जोड़ना था और डेटाबेस का नाम बदलना था, लेकिन यह काम करता है। TY
lzap

1
मेरे लिए समान ... "sudo xargs मार" और हार्ड-कोडित db_name में बदलकर "my-development-database-name"
केविन देवल्ट

6
task "db:drop" => :kill_postgres_connectionsमुझे लगता है कि इस लाइन को हटा दिया जाना चाहिए, यह मेरे दृष्टिकोण से, सिस्टम कार्य के व्यवहार का विस्तार करने के लिए खतरा है।
msa.im

: बल्कि hardcode से अपने डेटाबेस का नाम, बस निम्न का उपयोग करdb_name = Rails.configuration.database_configuration[Rails.env]['database']
ताल

40

आसान और अधिक अद्यतन तरीका है: 1. ps -ef | grep postgresकनेक्शन # 2 खोजने के लिए उपयोग करें ।sudo kill -9 "# of the connection

नोट: समान पीआईडी ​​हो सकती है। एक को मारना सबको मार देता है।


परिणाम में कौन सी संख्या पीआईडी ​​का प्रतिनिधित्व करती है? मुझे पीआईडी ​​की तरह दिखने वाले नंबरों के साथ 3 अनलेबेड कॉलम दिखाई देते हैं।
ब्रैडग्रेन

2
@ ब्रैडगर्न्स दूसरे कॉलम (मैं मैक टर्मिनल का उपयोग कर रहा हूं)
s2t2

पीएस के साथ कुछ भी नहीं मिला है, लेकिन अभी भी डीबी: ड्रॉप पर त्रुटि मिलती है।
जोसेफ

17

यहां आपके पोस्टग्रेज डेटाबेस के सभी कनेक्शनों को मारने का एक त्वरित तरीका है।

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

चेतावनी: यह postgresउपयोगकर्ता द्वारा चलाए जा रहे किसी भी चलने वाली प्रक्रिया को मार देगा , इसलिए सुनिश्चित करें कि आप इसे पहले करना चाहते हैं।


11
मेरे सिस्टम में मैं sudo kill -9 `ps -u postgres -o pid=` इसके बजाय उपयोग करता हूं , इसलिए एक पीआईडी हैडर द्वारा मुद्रित नहीं किया जाएगा ps, इसलिए एक स्ट्रिंग तर्क पारित नहीं किया जाता है kill, इसलिए एक त्रुटि नहीं उठाई जाएगी। किसी भी मामले में महान टिप।
विगत

1
मैं उत्थित और नीचा दिखा रहा हूं, जिसके परिणामस्वरूप लगभग शून्य रेटिंग मिली है। एक विवादास्पद लगता है "त्वरित ठीक।" मुझे बस रिकॉर्ड है कि मैं के लिए राज्य चलो किया था एक चेतावनी है कि यह खतरनाक है दे। :)
जामोन होल्मग्रेन

3
यदि आप उबंटू पर हैं, तो पोस्टग्रैसक्ले को फिर से शुरू करने के लिए इसका उपयोग करें:sudo service postgresql start
फ्राइस्टर

9

जब हमने ऊपर से "मार प्रक्रिया" विधि का उपयोग किया था, तो db: drop विफल हो रहा था (यदि: kill_postgres_connections पूर्वापेक्षित था)। मेरा मानना ​​है कि इसका कारण यह था कि रेक कमांड का उपयोग करने वाला कनेक्शन मारा जा रहा था। इसके बजाय, हम कनेक्शन को छोड़ने के लिए एक sql कमांड का उपयोग कर रहे हैं। यह DB के लिए एक शर्त के रूप में काम करता है: ड्रॉप, बल्कि जटिल कमांड के माध्यम से प्रक्रियाओं को मारने के जोखिम से बचा जाता है, और इसे किसी भी ओएस पर काम करना चाहिए (gentoo के लिए अलग सिंटैक्स आवश्यक है kill)।

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

यहाँ एक रेक कार्य है जो डेटाबेस का नाम डेटाबेस से पढ़ता है ।yml और एक बेहतर (IMHO) कमांड चलाता है। यह db को भी जोड़ता है: Kill_postgres_connections db: drop के लिए एक शर्त के रूप में। इसमें एक चेतावनी शामिल है जो आपके द्वारा पटरियों को अपग्रेड करने के बाद चिल्लाती है, यह दर्शाता है कि इस पैच की अब आवश्यकता नहीं हो सकती है।

देखें: https://gist.github.com/4455341 , संदर्भ शामिल हैं


8

मैं रेल 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

क्या आपने कभी उस उत्पादन चेतावनी को पढ़ना समाप्त किया है? बस जिज्ञासु: पी
विनीसियस ब्रासिल

6

कृपया जांच लें कि क्या आपका रेल कंसोल या सर्वर दूसरे टैब में चल रहा है और फिर

रेल सर्वर और कंसोल को बंद करें।

फिर भागो

 rake db:drop

5

जब आपका काम पूरा हो जाए तो अपने आवेदन को बंद कर दें। PostgreSQL कनेक्शन खुला नहीं रखता है, यह कनेक्शन को रखने वाला एप्लिकेशन है।


1
मैं phpgadmin के इंटरफ़ेस का उपयोग करके डेटाबेस को हटा सकता हूं लेकिन रेक कार्य के साथ नहीं। मैं फेकगैडमिन की ड्रॉप को एक रेक कार्य के साथ कैसे दोहरा सकता हूं?
fjuan

क्षमा करें, आप वहां मदद नहीं कर सकते, मुझे रेक के साथ कोई अनुभव नहीं है। लेकिन, त्रुटि इंगित करती है कि कोई अन्य उपयोगकर्ता अभी भी डेटाबेस का उपयोग कर रहा है। यही कारण है कि आप डेटाबेस को डिलीट नहीं कर सकते, न कि PhpPgAdmin द्वारा, असंभव। मैनुअल से, DROP DATABASE: इसे तब तक निष्पादित नहीं किया जा सकता है जब आप या कोई और लक्ष्य डेटाबेस से जुड़ा हो।
फ्रैंक हाइकेंस

3

रेल संभवतः इसे गिराने के लिए डेटाबेस से जुड़ रही है, लेकिन जब आप phppgadmin के माध्यम से लॉग इन करते हैं तो यह टेम्पलेट 1 के माध्यम से लॉगिंग करता है या डेटाबेस को पोस्टग्रेट करता है, इस प्रकार आप इससे प्रभावित नहीं होते हैं।


मैं डेटाबेस को छोड़ने के लिए रेल को कैसे बाध्य कर सकता हूं? क्या मुझे SQL कमांडों को पोस्ट करने के लिए अपनी खुद की रैक कार्रवाई को परिभाषित करना चाहिए?
fjuan

2

मैंने pgreset नामक एक मणि लिखी है जो रेक db: drop (or db: reset, etc) चलाने पर अपने आप ही डेटाबेस में कनेक्शन को मार देगा। आपको बस इसे अपने जेमफाइल में जोड़ना है और इस मुद्दे को दूर करना चाहिए। इस लेखन के समय यह रेल 4 और ऊपर के साथ काम करता है और इसे पोस्टग्रैज 9.x पर परीक्षण किया गया है। स्रोत कोड रुचि रखने वाले किसी भी व्यक्ति के लिए जीथब पर उपलब्ध है ।

gem 'pgreset'

कुछ नहीं, लेकिन आपका मणि ऐसा करेगा - कनेक्शन मौजूद नहीं था (ps grep खोज आदि), लेकिन रेल ने सोचा कि यह किया है। बहुत धन्यवाद!!
जोसेफ

2

इसने मेरे लिए काम किया (रेल 6): rake db:drop:_unsafe

मुझे लगता है कि हमारे पास हमारे कोडबेस में कुछ था जिसने रेक कार्य को छोड़ने से पहले एक db कनेक्शन शुरू किया।


1

आप बस ActiveRecord कोड को छोड़ सकते हैं जो ड्रॉपिंग करता है।

रेल के लिए 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

रेल के लिए 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/ )


1

जब उत्पादन में एक रेल 5.2 अनुप्रयोग और पोस्टग्रेक्यूएल डेटाबेस के साथ काम करते समय मेरे पास यही मुद्दा था।

यहां मैंने इसे हल किया है :

सबसे पहले, डेटाबेस सर्वर पर हर कनेक्शन को लॉग आउट करें PGAdmin क्लाइंट यदि कोई हो।

टर्मिनल से डेटाबेस का उपयोग करके हर सत्र को रोकें।

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

PostgreSQL सर्वर को प्रारंभ करें, क्योंकि ऊपर दिए गए मार ऑपरेशन ने PostgreSQL सर्वर को रोक दिया है।

sudo systemctl start postgresql

उत्पादन वातावरण में डेटाबेस छोड़ उत्पादन तर्कों को जोड़ रहा है।

rails db:drop RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1

बस इतना ही।

आशा है कि ये आपकी मदद करेगा


0

बस यह सुनिश्चित करें कि आपने किसी खुली टर्मिनल विंडो पर रेल कंसोल को बाहर निकाल दिया है और रेल सर्वर को बाहर कर दिया है ... यह लोगों द्वारा की गई सबसे आम गलती में से एक है


0

मैंने कहा कि 1 उपयोगकर्ता डेटाबेस का उपयोग कर रहा था, मुझे एक समान त्रुटि थी, मुझे एहसास हुआ कि यह मुझे था! मैंने अपने रेल सर्वर को बंद कर दिया और फिर रेक किया: ड्रॉप कमांड और यह काम किया!


0

सर्वर या कंप्यूटर को पुनरारंभ करने के बाद, कृपया पुनः प्रयास करें।

यह सरल उपाय हो सकता है।


0

समाधान

बैश लिपि

ENV=development

# restart postgresql
brew services restart postgresql

# get name of the db from rails app
RAILS_CONSOLE_COMMAND="bundle exec rails c -e $ENV"
DB_NAME=$(echo 'ActiveRecord::Base.connection_config[:database]' | $RAILS_CONSOLE_COMMAND | tail -2 | tr -d '\"')

# delete all connections to $DB_NAME
for pid in $(ps -ef | grep $DB_NAME | awk {'print$2'})
do
   kill -9 $pid
done

# drop db
DISABLE_DATABASE_ENVIRONMENT_CHECK=1 RAILS_ENV=$ENV bundle exec rails db:drop:_unsafe
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.