106 votes

Erreur de dépôt Rails + Postgres: d'autres utilisateurs ont accès à la base de données.

J'ai une application rails de l'exécution sur Postgres.

J'ai deux serveurs: un pour les tests et l'autre pour la production.

Très souvent j'ai besoin de cloner la base de données de production sur le serveur de test.

La commande je suis de running par Vlad est:

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

Le problème que je rencontre est que je reçois l'erreur suivante:

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

Ce qui se passe si quelqu'un a accès à l'application via le web récemment (postgres conserve une "session" ouverte)

Est-il possible que je peux mettre fin à la session sur la postgres DB?

Je vous remercie.

Modifier

Je peux supprimer la base de données à l'aide de phppgadmin de l'interface, mais pas avec la tâche rake.

Comment puis-je reproduire phppgadmin, la baisse avec une tâche rake?

85voto

encoded Points 656

Si vous supprimez les connexions postgresql en cours d'exécution pour votre application, vous pouvez alors exécuter db: drop, sans problème. Alors, comment tuer ces connexions? J'utilise la tâche de rake suivante:

 # 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
 

Si vous tuez les connexions sous les rails, cela risque de provoquer un échec la prochaine fois que vous essayez de charger une page, mais son rechargement rétablit la connexion.

17voto

Jamon Holmgren Points 7176

Voici un moyen rapide de supprimer toutes les connexions à votre base de données postgres.

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

Attention: cela va tuer tous les processus en cours que l'utilisateur postgres est ouvert, assurez-vous donc de le faire en premier.

9voto

Matt Scilipoti Points 410

Lorsque nous avons utilisé le "tuer le processus" méthode à partir de ci-dessus, la db:baisse a été à l'échec (si :kill_postgres_connections était une condition préalable). Je crois que c'était parce que la connexion qui que râteau de commande a l'aide a été tué. Au lieu de cela, nous sommes à l'aide d'une commande sql pour supprimer la connexion. Cela fonctionne comme une condition préalable pour la db:drop, permet d'éviter le risque de tuer un processus par l'intermédiaire d'un complexe de commande, et il devrait fonctionner sur n'importe quel OS (gentoo requis une syntaxe différente pour kill).

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

Ici est une tâche rake qui lit la base de données nom de la base de données.yml et exécute une meilleure (à mon humble avis) de commande. Il ajoute également db:kill_postgres_connections comme une condition préalable à la db:drop. Il comprend un avertissement qui hurle après la mise à niveau des rails, ce qui indique que ce correctif peut ne plus être nécessaire.

voir: https://gist.github.com/4455341, références incluses

5voto

Frank Heikens Points 29270

Laissez votre application fermer la connexion une fois l'opération terminée. PostgreSQL ne garde pas les connexions ouvertes, c'est l'application qui garde la connexion.

3voto

Joshua D. Drake Points 667

Il est probable que Rails se connecte à la base de données pour la supprimer, mais lorsque vous vous connectez via phppgadmin, il se connecte via la base de données template1 ou postgres. Par conséquent, cela ne vous concerne pas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X