Pregunta Error de descarte de Rails + Postgres: otros usuarios están accediendo a la base de datos


Tengo una aplicación de rieles sobre Postgres.

Tengo dos servidores: uno para probar y el otro para producción.

Muy a menudo necesito clonar el DB de producción en el servidor de prueba.

El comando que estoy ejecutando a través de Vlad es:

rake RAILS_ENV='test_server' db:drop db:create

El problema que tengo es que recibo el siguiente error:

ActiveRecord::StatementInvalid: PGError: ERROR: database <database_name> is being accessed by other users DROP DATABASE IF EXISTS <database_name>

Esto sucede si alguien ha accedido a la aplicación a través de la web recientemente (postgres mantiene abierta una "sesión")

¿Hay alguna forma de que pueda finalizar las sesiones en la base de datos Postgres?

Gracias.

Editar

Puedo eliminar la base de datos usando la interfaz de phppgadmin, pero no con la tarea de rake.

¿Cómo puedo replicar la caída de phppgadmin con una tarea de rake?


74
2018-03-03 08:37


origen


Respuestas:


Si matas las conexiones postgresql en ejecución para tu aplicación, puedes ejecutar db: drop it fine. Entonces, ¿cómo matar esas conexiones? Uso la siguiente tarea de rake:

# 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

Eliminar las conexiones de debajo de los rieles a veces hará que estalle la próxima vez que intentes cargar una página, pero volver a cargarla restablece la conexión.


73
2018-04-21 23:06



Una manera más fácil y más actualizada es: 1. Uso ps -ef | grep postgres para encontrar la conexión # 2. sudo kill -9 "# of the connection

Nota: Puede haber un PID idéntico. Matar a uno mata a todos.


25
2017-10-02 02:06



Aquí hay una forma rápida de eliminar todas las conexiones a su base de datos postgres.

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

Advertencia: esto matará cualquier proceso en ejecución que el postgres el usuario tiene abierto, así que asegúrese de hacer esto primero.


16
2018-06-18 21:55



Cuando usamos el método "matar procesos" desde arriba, el db: drop estaba fallando (si: kill_postgres_connections era un requisito previo). Creo que fue porque la conexión que ese comando de rake estaba usando estaba siendo asesinada. En cambio, estamos usando un comando sql para soltar la conexión. Esto funciona como un prerrequisito para db: drop, evita el riesgo de matar procesos a través de un comando bastante complejo, y debería funcionar en cualquier sistema operativo (gentoo requiere una sintaxis diferente para kill)

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

Aquí hay una tarea de rake que lee el nombre de la base de datos de database.yml y ejecuta un comando mejorado (en mi humilde opinión). También agrega db: kill_postgres_connections como prerrequisito para db: drop. Incluye una advertencia que grita después de actualizar los rieles, lo que indica que este parche ya no es necesario.

ver: https://gist.github.com/4455341, referencias incluidas


9
2018-01-04 20:11



Deje que su aplicación cierre la conexión cuando esté lista. PostgreSQL no mantiene las conexiones abiertas, es la aplicación que mantiene la conexión.


5
2018-03-03 08:44



Utilizo la siguiente tarea de rake para anular los rieles drop_database método.

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

5
2018-03-31 12:38



Verifique si la consola de sus raíles o el servidor se está ejecutando en otra pestaña y luego

detener el servidor y la consola de los rieles.

entonces corre

 rake db:drop

4
2017-11-06 06:23



Es probable que Rails se conecte a la base de datos para soltarlo, pero cuando inicia sesión a través de phppgadmin, está iniciando sesión a través de la plantilla1 o la base de datos postgres, por lo que no se verá afectado.


3
2018-03-04 19:02



Usted puede simplemente monopatchear el código de ActiveRecord que realiza la caída.

Para 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

Para 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

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


1
2018-01-10 14:47



Escribí una gema llamada pgreset eso matará automáticamente las conexiones a la base de datos en cuestión cuando ejecute rake db: drop (o db: reset, etc). Todo lo que tienes que hacer es agregarlo a tu Gemfile y este problema debería desaparecer. En el momento de escribir estas líneas, funciona con Rails 4 en adelante y ha sido probado en Postgres 9.x. El código fuente está disponible en github para cualquier persona interesada

gem 'pgreset'

1
2017-09-29 21:43



Solo asegúrese de que haya salido de la consola de rieles en cualquier ventana de terminal abierta y haya salido del servidor de rieles ... este es uno de los errores más comunes cometidos por personas


0
2017-09-18 07:28