Saya memiliki aplikasi rel yang berjalan di atas Postgres.
Saya memiliki dua server: satu untuk pengujian dan yang lainnya untuk produksi.
Sangat sering saya perlu mengkloning DB produksi di server pengujian.
Perintah yang saya jalankan melalui Vlad adalah:
rake RAILS_ENV='test_server' db:drop db:create
Masalah yang saya alami adalah saya menerima kesalahan berikut ini:
ActiveRecord::StatementInvalid: PGError: ERROR: database <database_name> is being accessed by other users DROP DATABASE IF EXISTS <database_name>
Ini terjadi jika seseorang baru-baru ini mengakses aplikasi melalui web (postgres membuat "sesi" tetap terbuka)
Apakah ada cara agar saya dapat menghentikan sesi di DB postgres?
Terima kasih.
Edit
Saya dapat menghapus database menggunakan antarmuka phppgadmin tetapi tidak dengan tugas rake.
Bagaimana cara mereplikasi drop phppgadmin dengan rake task?
ruby-on-rails
postgresql
fjuan
sumber
sumber
Jawaban:
Jika Anda mematikan koneksi postgresql yang sedang berjalan untuk aplikasi Anda, Anda dapat menjalankan db: drop dengan baik. Jadi bagaimana cara mematikan koneksi tersebut? Saya menggunakan tugas menyapu berikut:
# 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
Mematikan koneksi dari bawah rel terkadang akan menyebabkannya muntah saat Anda mencoba memuat halaman lagi, tetapi memuatnya kembali akan membuat koneksi kembali.
sumber
task "db:drop" => :kill_postgres_connections
Saya pikir baris ini harus dihapus, berbahaya untuk memperluas perilaku tugas sistem, dari pandangan saya.db_name = Rails.configuration.database_configuration[Rails.env]['database']
Cara yang lebih mudah dan lebih update adalah: 1. Gunakan
ps -ef | grep postgres
untuk mencari koneksi # 2.sudo kill -9 "# of the connection
Catatan: Mungkin ada PID yang identik. Membunuh satu membunuh semua.
sumber
Berikut cara cepat untuk mematikan semua koneksi ke database postgres Anda.
sudo kill -9 `ps -u postgres -o pid`
Peringatan: ini akan menghentikan semua proses yang sedang berjalan yang
postgres
dibuka pengguna, jadi pastikan Anda ingin melakukan ini terlebih dahulu.sumber
sudo kill -9 `ps -u postgres -o pid=`
sebagai gantinya, jadi header PID tidak akan dicetak olehps
, jadi argumen string tidak diteruskankill
, jadi kesalahan tidak akan dimunculkan. Tip bagus dalam hal apapun.sudo service postgresql start
Ketika kami menggunakan metode "kill proses" dari atas, db: drop gagal (jika: kill_postgres_connections merupakan prasyarat). Saya percaya itu karena koneksi yang digunakan oleh perintah rake telah dimatikan. Sebagai gantinya, kami menggunakan perintah sql untuk memutuskan koneksi. Ini berfungsi sebagai prasyarat untuk db: drop, menghindari risiko mematikan proses melalui perintah yang agak rumit, dan harus bekerja pada OS apa pun (gentoo memerlukan sintaks yang berbeda
kill
).cmd = %(psql -c "SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE procpid <> pg_backend_pid();" -d '#{db_name}')
Berikut adalah tugas menyapu yang membaca nama database dari database.yml dan menjalankan perintah yang ditingkatkan (IMHO). Itu juga menambahkan db: kill_postgres_connections sebagai prasyarat untuk db: drop. Ini termasuk peringatan yang berteriak setelah Anda meningkatkan rel, menunjukkan bahwa tambalan ini mungkin tidak lagi diperlukan.
lihat: https://gist.github.com/4455341 , referensi disertakan
sumber
Saya menggunakan tugas rake berikut untuk mengganti
drop_database
metode Rails .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
sumber
Silakan periksa apakah konsol atau server rel Anda berjalan di tab lain dan kemudian
hentikan server rel dan konsol.
lalu lari
rake db:drop
sumber
Biarkan aplikasi Anda menutup koneksi setelah selesai. PostgreSQL tidak menjaga koneksi tetap terbuka, itu adalah aplikasi yang menjaga koneksi.
sumber
Rails kemungkinan akan terhubung ke database untuk menjatuhkannya tetapi ketika Anda masuk melalui phppgadmin, ia masuk melalui database template1 atau postgres, sehingga Anda tidak terpengaruh olehnya.
sumber
Saya menulis permata bernama pgreset yang secara otomatis akan mematikan koneksi ke database yang dimaksud ketika Anda menjalankan rake db: drop (atau db: reset, dll). Yang harus Anda lakukan adalah menambahkannya ke Gemfile Anda dan masalah ini akan hilang. Pada saat penulisan ini bekerja dengan Rails 4 dan lebih tinggi dan telah diuji pada Postgres 9.x. Kode sumber tersedia di github untuk siapa saja yang tertarik.
sumber
Ini berhasil untuk saya (rel 6):
rake db:drop:_unsafe
Saya pikir kami memiliki sesuatu di basis kode kami yang memulai koneksi db sebelum tugas rake mencoba menjatuhkannya.
sumber
Anda cukup mencocokkan kode ActiveRecord yang melakukan penurunan.
Untuk 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
Untuk 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
(dari: http://www.krautcomputing.com/blog/2014/01/10/how-to-drop-your-postgres-database-with-rails-4/ )
sumber
Saya mengalami masalah yang sama saat bekerja dengan aplikasi Rails 5.2 dan database PostgreSQL dalam produksi.
Inilah cara saya menyelesaikannya :
Pertama, logout setiap koneksi ke server database di Klien PGAdmin jika ada.
Hentikan setiap sesi menggunakan database dari terminal.
sudo kill -9 `ps -u postgres -o pid=`
Mulai server PostgreSQL, karena operasi kill di atas menghentikan server PostgreSQL.
sudo systemctl start postgresql
Jatuhkan database di lingkungan produksi dengan menambahkan argumen produksi.
rails db:drop RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1
Itu saja.
saya harap ini membantu
sumber
Pastikan bahwa Anda telah keluar dari konsol rel di jendela terminal yang terbuka dan keluar dari server rel ... ini adalah salah satu kesalahan paling umum yang dilakukan oleh orang-orang
sumber
Saya mengalami kesalahan serupa yang mengatakan 1 pengguna menggunakan database, saya menyadari itu adalah SAYA! Saya mematikan server rel saya dan kemudian melakukan perintah rake: drop dan berhasil!
sumber
Setelah server atau komputer dimulai ulang, coba lagi.
Ini bisa menjadi solusi sederhana.
sumber
Larutan
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
sumber