ruby-on-rails postgresql capistrano

ruby on rails - Capistrano con PostgreSQL, error: otros usuarios acceden a la base de datos



ruby-on-rails (3)

Tengo una aplicación de Rails que usa PostgreSQL como un backend con un entorno cert que intenta imitar la producción, excepto que necesita tener el restablecimiento de la base de datos periódicamente para QA.

Cuando intento ejecutar db:reset desde una tarea de Capistrano durante la implementación, aparece el error:

ERROR: database "database_name" is being accessed by other users

y la base de datos no se puede descartar como parte de la tarea de restablecimiento que da como resultado un error de implementación. ¿Hay alguna manera de restablecer las conexiones de la base de datos de Capistrano para poder eliminar la tabla con éxito? Podía funcionar el SQL a psql desde una tarea de Capistrano, pero me preguntaba si habría una mejor manera de hacerlo.


Con PostgreSQL puede emitir la siguiente declaración para devolver los pids de back-end de todas las conexiones abiertas, excepto esta:

SELECT pid FROM pg_stat_activity where pid <> pg_backend_pid();

Luego puede emitir una solicitud de terminación para cada uno de esos backends con

SELECT pg_terminate_backend($1);

Vinculación de los pids devueltos desde la primera declaración a cada ejecutivo pg_terminate_backend.

Si las otras conexiones no utilizan el mismo usuario que usted, tendrá que conectarse como superusuario para emitir con éxito los extremos.

ACTUALIZACIÓN: Incorporación de comentarios y expresión como tarea de Capistrano:

desc "Force disconnect of open backends and drop database" task :force_close_and_drop_db do dbname = ''your_database_name'' run "psql -U postgres", :data => <<-"PSQL" REVOKE CONNECT ON DATABASE #{dbname} FROM public; ALTER DATABASE #{dbname} CONNECTION LIMIT 0; SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE pid <> pg_backend_pid() AND datname=''#{dbname}''; DROP DATABASE #{dbname}; PSQL end


He combinado la respuesta de dbenhur con esta tarea de Capistrano para lograr el resultado que necesitaba, como un encanto:

desc ''kill pgsql users so database can be dropped'' task :kill_postgres_connections do run ''echo "SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE datname=/'database_name/';" | psql -U postgres'' end

Esto supone que el auth_method para el usuario postgres está configurado como ''trust'' en pg_hba.conf

Luego puede llamarlo en su tarea de implementación después de update_code y antes de migrate

after ''deploy:update_code'', ''kill_postgres_connections''


Simplemente puede hacer un "monkeypatch" en el código ActiveRecord que hace que se caiga.

Para rieles 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

Para rieles 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

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