У меня есть приложение rails, работающее над 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>
Это происходит, если кто-то недавно обращался к приложению через Интернет (postgres сохраняет «сеанс» открытым)
Есть ли способ завершить сеансы в базе данных postgres?
Спасибо.
редактировать
Я могу удалить базу данных с помощью интерфейса phppgadmin, но не с помощью задачи rake.
Как я могу воспроизвести падение phppgadmin с помощью rake task?
ruby-on-rails
postgresql
фьюань
источник
источник
Ответы:
Если вы убьете запущенные соединения 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
Удаление соединений из-под рельсов иногда приводит к тому, что при следующей попытке загрузить страницу он будет отключаться, но при повторной загрузке соединение восстанавливается.
источник
task "db:drop" => :kill_postgres_connections
Думаю, эту строчку нужно убрать, с моей точки зрения, это опасность расширения поведения системной задачи.db_name = Rails.configuration.database_configuration[Rails.env]['database']
Более простой и обновленный способ: 1. Используйте,
ps -ef | grep postgres
чтобы найти соединение №2.sudo kill -9 "# of the connection
Примечание: могут быть идентичные PID. Убийство одного убивает всех.
источник
Вот быстрый способ убить все подключения к вашей базе данных postgres.
sudo kill -9 `ps -u postgres -o pid`
Предупреждение: это убьет все запущенные процессы,
postgres
открытые пользователем, поэтому сначала убедитесь, что вы хотите это сделать.источник
sudo kill -9 `ps -u postgres -o pid=`
вместо этого, поэтому заголовок PID не будет напечатанps
, поэтому строковый аргумент не передаетсяkill
, поэтому ошибка не возникает. Отличный совет в любом случае.sudo service postgresql start
Когда мы использовали метод «уничтожения процессов», описанный выше, db: drop завершился ошибкой (если: kill_postgres_connections было предварительным условием). Я считаю, что это произошло потому, что соединение, которое использовала эта команда rake, было отключено. Вместо этого мы используем команду sql для разрыва соединения. Это работает как предварительное условие для db: drop, позволяет избежать риска прерывания процессов с помощью довольно сложной команды и должно работать в любой ОС (для gentoo требовался другой синтаксис
kill
).cmd = %(psql -c "SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE procpid <> pg_backend_pid();" -d '#{db_name}')
Вот задача rake, которая считывает имя базы данных из database.yml и запускает улучшенную (IMHO) команду. Он также добавляет db: kill_postgres_connections в качестве предварительного условия к db: drop. Он включает в себя предупреждение, которое кричит после обновления рельсов, указывая на то, что этот патч больше не нужен.
см .: https://gist.github.com/4455341 , включая ссылки
источник
Я использую следующую задачу rake, чтобы переопределить
drop_database
метод 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
источник
Пожалуйста, проверьте, работает ли ваша консоль или сервер rails на другой вкладке, а затем
остановите сервер рельсов и консоль.
затем беги
rake db:drop
источник
Позвольте вашему приложению закрыть соединение, когда это будет сделано. PostgreSQL не поддерживает соединения открытыми, это приложение поддерживает соединение.
источник
Rails, вероятно, подключается к базе данных, чтобы удалить ее, но когда вы входите в систему через phppgadmin, он входит в систему через базу данных template1 или postgres, поэтому вас это не касается.
источник
Это сработало для меня (рельсы 6):
rake db:drop:_unsafe
Я думаю, что у нас было что-то в нашей кодовой базе, которое инициировало соединение с базой данных до того, как задача rake попыталась его сбросить.
источник
Я написал гем под названием pgreset , который автоматически уничтожает соединения с рассматриваемой базой данных, когда вы запускаете rake db: drop (или db: reset и т. Д.). Все, что вам нужно сделать, это добавить его в свой Gemfile, и эта проблема должна исчезнуть. На момент написания он работал с Rails 4 и новее и был протестирован на Postgres 9.x. Исходный код доступен на github для всех желающих.
источник
Вы можете просто исправить код 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
(с: http://www.krautcomputing.com/blog/2014/01/10/how-to-drop-your-postgres-database-with-rails-4/ )
источник
У меня была такая же проблема при работе с приложением Rails 5.2 и базой данных PostgreSQL в производственной среде.
Вот как я это решил :
Во-первых, выходите из каждого подключения к серверу базы данных на клиенте 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
Вот и все.
надеюсь, это поможет
источник
Просто убедитесь, что вы вышли из консоли rails в любом открытом окне терминала и вышли из сервера rails ... это одна из самых распространенных ошибок, которые делают люди.
источник
У меня была аналогичная ошибка, говоря, что 1 пользователь использовал базу данных, я понял, что это Я! Я выключил свой сервер rails, а затем выполнил команду rake: drop, и это сработало!
источник
После перезапуска сервера или компьютера попробуйте еще раз.
Это могло быть простое решение.
источник
Решение
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
источник