SQLSTATE too many connections

a marqué ce sujet comme résolu.

Bonjour à tous,

J’ai encore un soucis avec mon application qui est en cours de mise en production. C’est une petite application de gestion pour une entreprise et celle-ci est hébergé chez OVH en tant que sous-domaine de leur site principal.

En ce moment de façon assez régulière on me rapporte des erreurs que voici : SQLSTATE : Too many connections. J’ai fait quelques recherches sur le web et tout ce que j’ai trouvé indique éventuellement trop d’utilisateurs pour la base de donnée.

Seulement pour l’instant il y’a seulement une personne qui s’en occupe et moi de temps en temps donc est-ce vraiment ça ? Est-ce que ça peut venir aussi du fait qu’il soit placé en sous-domaine et du coup le site + l’application donne une trop grosse charge à la base de donnée ?

Autre hypothèse que j’ai pu voir et qui me plaît moins, peut-être le fait que je ne ferme pas mes requêtes à l’aide de "CloseCursor", vous pensez que ça peut venir de là ? J’avoue ne m’être jamais soucié de ce genre de chose, mais si il faut tout modifier je le ferais…

Si quelqu’un peut m’éclairer la dessus ce serait très gentil. Merci d’avance :)

EDIT : Apparemment voici ce que me donne MySQL concernant le nombre de connexions autorisées : max_connections - 300 max_user_connections - 30

+0 -0

Bonjour

Autre hypothèse que j’ai pu voir et qui me plaît moins, peut-être le fait que je ne ferme pas mes requêtes à l’aide de "CloseCursor"

Cela n’a rien à voir en fait. Je pense plutôt à un moment dans ton code où tu ouvres une connexion pour chaque requête. Pourrait-on voir ton code?

Finalement j’ai compris que CloseCursor permets de libérer la connexion quand on exécute 2 requêtes on peut faire un closeCursor après la première requête mais apparemment c’est inutile sous MySQL.

Voici des extraits de mon code. Au début de chaque page j’inclus mon fichier de connexion à la base de donnée comme ceci

require($ihm['classes_dir'].'/db_connect.php');

Dans lequel j’ai ce code

<?php try { $db = new PDO('mysql:host=localhost;dbname=nomDB;charset=utf8', 'root', '', array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); } catch (Exception $e) { die('Erreur : ' . $e->getMessage()); } ?>

Ensuite dans mes fichiers j’utilise mes requêtes comme ceci

$query = $db->query('SELECT * FROM clients ORDER BY societe ASC'); $clients = $query->fetchAll();

ou encore

$req = 'UPDATE clients SET code_client = :code_client WHERE id_client = :id_client'; $query = $db->prepare($req); $query->execute(array( 'code_client' => $code_client, 'id_client' => $id ));

Et il m’arrive parfois d’avoir ce genre de requêtes 4 ou 5 fois par page. Ça pourrait venir de là ?

J’ai débuté mon application il y’a plus d’un an et à l’époque j’avais moins de connaissances qu’aujourd’hui. Du coup aucune organisation c’est vraiment basique genre j’ai une page "liste-client.php" dans laquelle j’inclue mon header, ma connexion SQL et d’autres choses si besoin puis ensuite j’ai mes requêtes, affichage HTML etc… tout dans la même page et ça pour toute l’application.

Je sais que c’est pas terrible mais à l’époque je savais pas trop faire autrement :(

+0 -0

Hello !

Un problème classique c’est la réouverture de connexions pour un process répété plusieurs fois. i.e. si tu le fais 30fois tu vas avoir ton erreur. Si tu as besoin de re-créer de nouvelles connexions (ça arrive) il faut que tu fermes la connexion à la fin de ton process.

Il y a plusieurs cas de figure où ça peut arriver mais dans ton cas je pense plutôt que tu ouvres la connexion à chaque fois au lieu d’utiliser la même connexion à chaque fois ;) .

Comment je sais si j’ouvre à chaque fois une nouvelle connexion ? En incluant mon fichier de connexion dans lequel je spécifie "new PDO" ça veut dire que je créé une nouvelle connexion à chaque fois ?

Comment ferme t-on une connexion ? Du coup il faudrait que je la ferme à chaque fin de page ?

Oui, chaque $db = new PDO est une nouvelle connexion ! Pour la fermer il faut que tu utilises $db->closeCursor(). Attention tout de même car dès que tu vas réutiliser ta variable $db il va réouvrir la connexion.

[edit] d’après la doc une solution peut être plus efficace serait $db = null.

+0 -0

Pour la fermer il faut que tu utilises $db->closeCursor()

Ca ne met pas fin à la connexion, ça libère la connexion pour l’exécution d’une nouvelle requête : certains pilotes/sgbd ne permettent pas d’exécuter une nouvelle requête s’il y en a toujours une en cours (ie son jeu de résultat n’a pas été intégralement lu).

D’autant plus que closeCursor est une méthode de la classe PDOStatement et non PDO. On trouve d’ailleurs dans sa documentation une réimplémentation type en PHP/PDO si vous voulez vraiment comprendre quel est son rôle.

d’après la doc une solution peut être plus efficace serait $db = null

Ca ne suffit pas si des PDOStatement sont toujours instanciés car chaque instance de PDOStatement ajoute une référence à l’objet PDO (la mémoire en PHP étant gérée par un ramasse-miettes type comptage de références) dont ils sont issus. Si ce compteur n’est pas à 0, tu auras beau écraser ta variable par NULL (ou peu importe), l’objet PDO, y compris la connexion, subsistera en mémoire.

Comment ferme t-on une connexion ? Du coup il faudrait que je la ferme à chaque fin de page ?

Ce n’est pas utile de le faire "à la main" sauf si le script est vraiment long et que tu n’as plus besoin de ta bdd sur sa fin puisque PHP s’occupe de libérer les ressources et fermer toute connexion (non persistante), fichiers, etc automatiquement à la fin de tout script.


Comme l’a dit Nek, tu ne ferais pas tout simplement plusieurs require($ihm['classes_dir'].'/db_connect.php'); par "script" ? Ce qui en multiplierait d’autant le nombre de connexions.

A moins vraiment d’avoir trop de trafic et/ou de renvoyer inutilement des requêtes HTTP à PHP (suffit d’une réécriture).

+0 -0

Merci de vos réponses je commence a comprendre un peu mon problème.

Si, effectivement sur chaque page que l’utilisateur visite je fais mon require et du coup je crée une nouvelle connexion à chaque fois.

Mais du coup comment je peux faire pour savoir si la connexion est ouverte ou non ?

Encore merci à vous :)

Du coup ta solution c’est surtout d’utiliser la même instance de pdo partout. (encore une fois y’a des cas où ça n’est pas possible!)

Sinon une bonne autre solution c’est d’utiliser le dbal de Doctrine qui est juste beaucoup mieux (c’est une couche au dessus de pdo) et qui a la fameuse méthode ->close()

DBAL pour « database abstraction & access layer ». Doctrine est la librairie de gestion de base de données de référence en PHP, et on l’utilise plus souvent avec son ORM – a.k.a. Object Relation Mapping – mais le DBAL est tout de même pratique (et plus simple) !

Salut,

Juste une question annexe : les identifiants de la BD que tu as mis dans ton deuxième post ne sont pas ceux réellement utilisés ?

Parce que si c’est le cas, c’est assez embêtant d’utiliser les identifiants par défaut pour un système en production.

Pour revenir à ton soucis. L’hébergement est un VPS ou un hébergement web classique ?
La BD est la même que pour leur site principale ?

Salut,

Pour les identifiants BDD ce sont ceux pour le développement en local.

C’est un hébergement web classique. J’ai corrigé mon problème de nouvelle connexion à chaque page en testant si la connexion existe déjà ou non.

Pour l’instant l’erreur n’est pas réapparu mais je surveille et fait de nombreux tests quand même.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte