Forum Clubic

Nombre de connection MYSQL (transaction) [résolu]

Bonjour

Lorsque plusieurs personnes se connectent à un site en php avec MYSQL derriere, la simultanéité n’existant pas en informatique (sauf peut être avec les multi-proccesseurs) les requetes sont effectuées les unes derrieres les autres, ce qu’on ne peut pas percevoir vu que ca prend quelques millièmes de secondes…

Par contre, j’aimerai savoir si il est possible d’avoir plusieurs connection active en même temps pour un même utilisateur MYSQL (= même serveur web qui interroge la même bdd pour plusieurs internautes en même temps) puisqu’on peut ouvrir puis fermer plus tard la connection avec la bdd, à ce moment là la superposition des connections est possible…

Les requetes se font forcément l’une derriere l’autre même si elles semblent simultanées, mais est ce qu’on peut avoir plusieurs connections d’ouverte pour le même utilisateur MYSQL, ou est ce que la 2nd requete envoyée par le navigateur du second internaute devra attendre la fermeture de la connection ouverte par la requete du 1er pour pouvoir ouvrir sa connection et interroger la bdd ?

Si on peut avoir plusieurs connections ouvertes en même temps pour le même utilisateur, existe-t-il une option lorsqu’on crée un utilisateur MYSQL pour définir le nombre de connections ouvertes en même temps ?

Si je nai pas été clair n’hésitez pas à me faire préciser ma pensée :wink:

pas tres clair en effet

il faut savoir que sur un serveur web mutualisé par exemple, il y a en general entre 5 et 10 connexion simultanée (config mysql), ce ki est amplement suffisant pour plusieurs centaines d’utilisateurs.

si tu veux savoir si plusieur connexions sur la mm bdd accelere le processus de requetage, non car si il s’agit d’1 seul srv sql, les requetes seront tjrs effectué les unes derrieres les autres.

Tu a cependant la possibilité de créer plusieur connexions sur des bdd differentes, voire la mm (mais cela ne sert a rien)

ex:

//CONNEXION AU SERVEUR DISTANT
$remote = @mysql_connect("$rhost","$rlogin","$rpwd");

//CONNEXION AU SERVEUR LOCAL
$local = @mysql_connect("$lhost","$llogin","$lpwd");

Bien a toi :slight_smile:

ps: ensuite tu peux utiliser l’identifiant de connexion lorsque tu fé un query en specifiant bien quel id de connexion tu utilise (donc quelle base logikement…)

Admettons que j’ai un forum en php par exemple, avec un fichier de config dans leqeul est définit les paramètre de connection d’un unique utilisateur MYSQL (un login + un mdp + adresse du serveur MYSQL + la base de donnée)

Je sais que si plusieurs personne surfent exactement en même temps sur le forum et qu’elles clickent quasiement en même temps, la simultanéité n’existant pas les requettes vont arriver l’une apres l’autre (y aura forcément une première et une seconde) et le CPU ne pouvant pas non plus en traiter 2 en même temps (sauf multi-cpu dans certains cas) les requetes sont exécuté l’une derriere l’autre.

Par contre entre la requete qui ne dure que quelques millisecondes et la connection il y a une différence qui est que la requete dure le temps d’etre calculée, alors que la connection est “pilotée” par le serveur web dont le code php ouvre, puis referme (ou non) la connection. La connection peut donc durée un certain temps (temps de l’execution du script php si on considère que le scritp referme la connection à la fin).

Ma question est donc, vu que la connection peut durer jusqu’à quelques secondes, est ce que le serveur web qui a reçu plusieurs requetes des internautes ouvre plusieurs connections vers le serveur MYSQL pour le même utilisateur MYSQL (puisqu’il n’en connait qu’un d’apres le cfg du script) pour répondre aux autres internautes rapidement même si le script lancé par le 1er n’est pas finit et donc la 1ere connection toujours active, ou bien si le serveur web attend que la connection soit fermée pour la réouvrir afin d’envoyer les requetes suivantes (ce qui dasn le cas d’un script dont les calculs seraient assez long ferait patienter les internautes suivants.

Autre exemple peut etre plus clair :

Un internaute appelle une page qui lance un script php.

Ce script ouvre une connection MYSQL a l’aide d’un login et d’un mdp, puis execute un SELECT sur la bdd MYSQL, effectue quelques calculs, puis execute un UPDATE sur la bdd, referme la connection MYSQL et renvoie la page html à l’internaute.

Admettons que le calcul php prenne 5 secondes, donc que la connection reste ouverte pendant 5 secondes.

1 seconde apres que mon premier internaute ai appelé la page, un second appelle la même page, le serveur lance donc en parallèle un nouveau processus avec le même script php.

que se passe-t-il au moment ou le nouveau processus tente d’ouvrir une connection à la base de donnée avec les même login et mdp ?

est ce que la connection lui est refusé ?
est ce que le 2nd script est mis en attente le temps que le premier script libère la connection ?
est ce que le processus en parallèle ouvre une nouvelle connection en parallèle de la première et poursuit son exécution de manière similaire ?

Dans le cas ou ce serai la dernière solution, existe t il des paramètres à spécifier lors de la création d’un user MYSQL pour définr le nombre de connection simultanée à la bdd ?

La deuxième connexion patientera que la première est fini.
Mais si t’as un script PHP qui prend plus de 5 secondes en requêtes MySQL, laisse tomber le PHP. :smiley:

D’apres mon experience personelle (à moi tout seul :smiley: ), je pense pouvoir dire que ça ne se passera pas comme ça. Les deux connexions seront bien effectuées, et les requetes s’executeront en parallele (virtuellement bien sur). Par contre le nombre d’utilisateurs connectés simultanement à la base mysql est limité par la variable max_connections. Si plus de max_connections + 1 utilisateurs sont connectés, la base retournera un message “Too many connections”. Donc si tu veux que le script attende que la première connexion soit finie, il va falloir que tu l’implementes toi même (par exemple une boucle sur la connection jusqu’à que tu ne recoies plus le message d’erreur, c’est barbare mais ça marche :)).

La variable max_connections est par défaut à 100, mais est souvent réduite par les hébergeurs à 10, voire à 3.

Je vais prendre un exemple de forum puisque c’est ça qui a l’air de t’interesser.

Si tu as une requete qui bouffe 75% de ton CPU (par ce qu’un user cherche le mot “le” sur un forum ou il y a 2 millions de messages ce qui est au passage dangereux de laisser faire une recherche sur - de 3 caracteres :stuck_out_tongue: ) et que tu as en gros 100 utilisateurs simultannés.

Ce qui va se passer, il va y avoir une queue monstre de requetes, elles vont etres traitées les unes a la suite des autres, le processus qui bouffe énormement de CPU va se faire scheduler mais sera un poil + prioritaire , et globalement tu va avoir ton forum qui va ramer totalement, et la charge de ton serveur exploser.

Apres a toi de choisir un compromis, performance/nb user.

Les 5 secondes c’était pour bien montrer que la connection peut être ouverte un certain temps pendant lequel une autre connection peut être demandée…

En fait c’est plus pour comprendre comment ca se passe…

Mon problème derrier ressemble à ça :

admettons que j’ai dans ma base une valeur à 1 qui représente par exemple quelque chose en stock, 1 étant la quantité.

Une premiere personne appele un script pour prendre ce stock, mais en fait il y a une certaine quantité de calcul à faire qui peuvent être plus ou moins long (pour le moment je n’ai pas encore un ordre de grandeur en tête, mais ce qui marche pour 5 secondes marche aussi pour 1/10 de seconde, seule la probabilité que le script soit lancé 2 fois dans cet interval diminue mais le fonctionnement lui est le même) et au final change le stock à 0.

Si pendant que les calculs se font, une seconde personne lance le même script afin de s’approprier le même stock, au moment ou le script va interroger la base, si les connections peuvent être ouverte en même temps, le second script pourra se baser sur le stock de 1 avant que le 1er script n’ai mis a jour la base pour dire qu’en fait il en reste 0.

Si le second script doit attendre que la connection soit libéré, pas de problème, si je peux limité le nombre de connection de l’utilisateur MYSQL à 1, ca revient au même (sauf que j’aurai en retour une erreur de nombre de connection max atteinte à gerer).

Le problème c’est que je ne sais pas comment ca se passe, donc je ne sais pas comment le gérer.

Cet un exemple tres simplifié juste pour voir le mode de fonctionnement, à partir du mode de fonctionnement à moi ensuite de gerer mon script pour éviter des bugs à cause d’acces simultanés à la bdd… Même si la probabilité que ca bug au finale est ridicule, elle existe donc autant ne pas laisser un bug possible se mettre en place…

le forum n’était qu’un exemple de script, mais ca ne sera pas un forum…

Le problème ne se situe pas au niveau de la requete elle même mais de l’acces à la base de donnée entre 2 requetes par un nouveau processus du même script, pendant que le premier script execute ces calculs.

Il faut savoir qu’en règle générale, le temps d’éxecution d’un script php est négligeable devant le temps d’execution des requetes vers la bdd. En partant de ce principe, en executant la requete de mise à jour en section critique, il ne devrait pas y avoir de problème. La question est : comment executer la requete en section critique ? :smiley: J’avais vu ça par hasard sur un site, je vais essayer de retrouver ça dès que j’ai le temps (je dois dire que ça m’interesse :slight_smile: )

T’inquiete pas de ce coté la c’est le SGBD qui gere la gestion des concurrences. il n’y aura pas d’incoherence du type appli a 0 et base a 1

J’ai trouvé quelque chose d’interessant :
http://www-eleves-isia.cma.fr/documentation/MysqlDoc/docMySQL3.23_v4c/manuel_LOCK_TABLES.html#LOCK_TABLES

En utilisant ça, il suffirait de placer un verrou entre le SELECT et l’UPDATE.

MERCI :wink:

C’était uen solution que j’avais envisagé, regarder du coté de MYSQL pour locké ma table pendant que je bosse dessus… J’avais pas chercher plus loin pour le moemnt vu que je ne savais pas comment ca se passait en vrai…

Pour le temps d’exécution, j’ai un nombre de tache qui vont s’accumuler et être exécuté d’un coup, le temps d’exécution php peut donc être variable et pour le moemnt comme ca n’est pas encore codé j’ai aucune notion du délais que ca pourra prendre dans les cas extrèmes…

Donc je ne peux pas partir sur le principe que le temps d’exécution ets négligeable et que ca n’a pratiqueemnt aucune chance d’arriver… comme pour le moment je ne maitrise rien je préfère parrer à toute éventualité (et en même temps ca me fait apprendre de nouvelle chose sur MYSQL)

le serveur MYSQL est indépendant du serveur web qui fait tourner PHP, je vois pas comment le serveur MYSQL peut de lui même se débrouiller pour garder la syncro entre ses valeurs et celles stocké dans les variables PHP, pour moi (corrigez moi si je me trompe) la base de donnée se fiche complètement de qui fait quoi avec ses valeurs, elle répond juste aux SELECT et UPDATE et c’est tout, à moi de faire gaffe de pas avoir des SELECT avant mon UPDATE pour “syncrhonisé” les différents thread PHP. La base elel a aucune idée que je vais faire un UPDATE apres mon SELECT et si ele recoit un autre SELECT ben elle va lui répondre sans savoir ce qu’on va en faire derrier.

Tout à fait.
Pour l’histoire du stock, c’est à toi dans ton script PHP de vérifier que le stock est toujours à 1 au moment même de la requête. C’est d’ailleurs à cause de ce genre de situation qu’il n’est pas toujours aisée de regrouper les requêtes ensemble même si c’est plus efficace.

Ah scuse moi, on s’est mal compris, j’ai cru que tu parlé de la concurence au niveau du serveur :frowning: (faut dire que tes explications sont pas tjrs tres claires :stuck_out_tongue: ).

Typiquement la ton problème c’est un problème de transaction.

le lien de kookiz33 contient la réponse à ma question ET la solution qui va avec :wink:

C’est bien un problème de transaction pthichat :wink:

Pas facile de se faire comprendre parfois :wink:

Merci de votre aide