web-dev-qa-db-fra.com

Heroku Postgres: Trop de connexions. Comment puis-je tuer ces connexions?

J'ai une application en cours d'exécution sur Heroku. Cette application a un addon Postgres 9.2.4 (Dev) installé. Pour accéder à ma base de données en ligne, j'utilise Navicat Postgres. Parfois, Navicat ne ferme pas proprement les connexions qu'il établit avec la base de données Postgres. Le résultat est qu'après un certain temps, il y a plus de 20 connexions ouvertes à la base de données Postgres. Mes installations Postgres ne permettent que 20 connexions simultanées. Donc, avec les 20+ connexions ouvertes, ma base de données Postgress est désormais inaccessible (trop de connexions).

Je sais que c'est un problème de Navicat et j'essaie de résoudre ce problème à cette fin. Mais si cela se produit (qu'il y a trop de connexions), comment puis-je résoudre ce problème (par exemple, fermer toutes les connexions).

J'ai essayé toutes les choses suivantes, sans résultat.

  • Navicat fermé et redémarré mon ordinateur (OS X 10.9)
  • Redémarrage de mon application Heroku (heroku restart)
  • J'ai essayé de redémarrer la base de données en ligne, mais j'ai découvert qu'il n'y avait pas d'option pour le faire
  • Fermeture manuelle de toutes les connexions d'OS X à l'IP du serveur Postgres
  • Redémarré notre routeur

Je pense qu'il est évident qu'il y a des connexions "mortes" du côté de Postgres. Mais comment les fermer?

31
Jasper Schulte

Regardez peut-être ce que heroku pg:kill peut faire pour vous? https://devcenter.heroku.com/articles/heroku-postgresql#pg-ps-pg-kill-pg-killall

32
John Beynon

heroku pg:killall va tuer toutes les connexions ouvertes, mais cela peut être un instrument contondant pour vos besoins. Fait intéressant, vous pouvez réellement tuer des connexions spécifiques en utilisant les fiches de données de Heroku.

Pour obtenir une liste détaillée des connexions, vous pouvez interroger via des clips de données:

SELECT * FROM pg_stat_activity;

Dans certains cas, vous souhaiterez peut-être supprimer toutes les connexions associées à une adresse IP (votre ordinateur portable ou, dans mon cas, un serveur qui a été détruit).

Vous pouvez voir combien de connexions appartiennent à chaque IP client en utilisant:

SELECT client_addr, count(*) 
FROM pg_stat_activity 
WHERE client_addr is not null 
  AND client_addr <> (select client_addr from pg_stat_activity where pid=pg_backend_Tid()) 
GROUP BY client_addr; 

qui listera le nombre de connexions par IP à l'exclusion de l'IP que les clips de données eux-mêmes utilisent.

Pour réellement tuer les connexions, vous passez leur "pid" à pg_terminate_backend (). Dans le cas simple:

SELECT pg_terminate_backend(1234)

où 1234 est le PID incriminé que vous avez trouvé dans pg_stat_activity.

Dans mon cas, je voulais tuer toutes les connexions associées à un serveur (maintenant mort), j'ai donc utilisé:

SELECT pg_terminate_backend(pid), Host(client_addr) 
FROM pg_stat_activity 
WHERE Host(client_addr) = 'IP HERE'
15
mgojohn

De la documentation Herok (c'est moi qui souligne):

FATAL: trop de connexions pour le rôle

FATAL: trop de connexions pour le rôle "[nom du rôle]" Cela se produit sur les plans Starter Tier (dev et basique), qui ont une limite de connexion maximale de 20 par utilisateur. Pour résoudre cette erreur, fermez certaines connexions à votre base de données en arrêtant les travailleurs en arrière-plan, en réduisant le nombre de dynos ou en redémarrant votre application au cas où elle aurait créé des fuites de connexion au fil du temps. Une discussion sur la gestion des connexions dans une application Rails peut être trouvée ici.

Parce que Heroku ne fournit pas d'accès superutilisateur vos options sont plutôt limitées à ce qui précède.

4
Robert H

Redémarrez le serveur

heroku restart --app <app_name>

Il fermera toute connexion et redémarrera.

2
Ebin Joy

En tant que superutilisateur (par exemple "postgres"), vous pouvez tuer chaque session sauf votre session actuelle avec une requête comme celle-ci:

select pg_cancel_backend(pid)
from pg_stat_activity
where pid <> pg_backend_pid();

S'ils ne disparaissent pas, vous devrez peut-être utiliser un "kill" plus fort, mais certainement tester avec pg_cancel_backend() en premier.

select pg_terminate_backend(pid)
from pg_stat_activity
where pid <> pg_backend_pid();
1
bma