Problème pour experts!

Nouveau WRInaute
Voila j'ai développé un jeu en php. Il y a une section marché qui permet de vendre et acheter des objets. Elle fonctionne bien tant qu'il n'y a pas trop d'utilisateur. Le nombre d'achats est limité à 20 par jour par utilisateur.

Un problème surgit quand il y a beaucoup d'utilisateurs connectés (+250), et que le serveur subit quelques ralentissement. Si quelqu'un clique frenetiquement sur le lien des dizaines de foi avant le chargement de la page, il arrive à faire plus de 20 achats!

dans ma bd, nbachats arrive à des résultats négatif.

succintement, voici le code:

Code:
$query = "SELECT nbachats FROM utilisateur WHERE id='$idmembre'";
$result= mysql_query($query);
$row = mysql_fetch_row($result);
if($row[0]<20){

$query = "UPDATE utilisateur SET nbachats=nbachats+1 WHERE id='$idmembre'"; 
$result = mysql_query($query);

//mes differentes operations

}
Comment cela est-il possible?
Y a-t-il une solution?

Merci
 
WRInaute discret
Salut,

Sur la page qui est la cible du lien, tu devrais faire un flush .

Code:
echo ' ';
flush();

Le echo permet d'ecrire quelque chose sur la page.
Le flush, renvoi le contenu de la page definie avant l'instruction "flush".
http://fr.php.net/flush

Cordialement,

FRed
 
WRInaute discret
Bonjour,

très intéressant ce problème de concurrence.

une instruction flush ne va faire que forcer l'envoie du buffer vers le navigateur, mais cela ne va pas permettre de gérer le problème si ce script est par exemple appelé deux fois simultanément (pile poil) par un utilisateur qui en est à 19 achats... ou je me trompe ?

Pour ma part, j'essaierais de faire le SELECT avec une priorité plus faible que la requete de mise à jour (UPDATE), histoire que celle-ci passe prioritairement dans le cas où plusieurs requêtes s'éxecutent simultanément..

Je ferais donc un truc comme ça pour vérifier le nbachats de l'utilisateur :
$query = "SELECT LOW PRIORITY nbachats FROM utilisateur WHERE id='$idmembre'";

De toutes facons, cela ne réglera pas les problème dans 100% des cas, mais je pense que la probabilité pour qu'il se manifeste devrait être diminué ?

Si tu essayes ma solution, tu me tiens au courant chameau STP ?
 
WRInaute impliqué
Faudrait utiliser un flag que tu passes à 1 dès que la requête est traitée. Si le flag est à 0 alors je traite la requête, sinon je traite pas. Ainsi tes requêtes dupliquées ne seront pas traitées.
 
WRInaute impliqué
Code:
$query = "SELECT nbachats FROM utilisateur WHERE id='$idmembre'";
$result= mysql_query($query);
$row = mysql_fetch_row($result);
if($row[0]<20){
$nbachats=$row[0]++;
$query = "UPDATE utilisateur SET nbachats='$nbachats' WHERE id='$idmembre'"; 
$result = mysql_query($query);
//mes differentes operations
}
else {
$query = "UPDATE utilisateur SET nbachats='20' WHERE id='$idmembre'"; 
$result = mysql_query($query);
}

Il y a un truc qui me chiffone, tu indique avoir nbachats negatifs ...
 
WRInaute accro
Une petite mousse pour revenir à des valeurs sures et concretes.... ;) bon courage les gars, on pense à vous !! :)
 
WRInaute occasionnel
pourquoi tu utilises pas un peu de javascript pour éviter que les utilisateurs ne cliquent plusieurs fois rapidement ? j'ai peut-être mal compris le problème, j'avoue
 
WRInaute occasionnel
Pourquoi ne pas tout faire en une seule requête ? Ça éviterat des pbs, non ?
Code:
UPDATE utilisateur SET nbachats=nbachats+1 WHERE id='$idmembre' AND nbachats < 20
Et tu testes le retour pour voir s'il y a eu une mise à jour ou pas. Si nb_affected_rows = 0, c'est que le max a été atteint, et que l'update n'a donc rien fait.
Ça devrait repporter le pb d'accès concurrents sur la base SQL plutô que sur la page PHP...
Bon, à vérifier quand même, hein....
 
WRInaute accro
Americas a dit:
on va se consoler en s'en jetant une au bar du coin ? :lol:

Code:
$query = "SELECT barducoin utilisateur WHERE id='$idpote'"; 
$result= mysql_query($query); 
$row = mysql_fetch_row($result); 
if($row[0]<20){ 
$nbachats=$row[0]++; 
$query = "UPDATE verre SET nbachats='$nbachats' MOUSSES id='$idpote'"; 
$result = mysql_query($query); 
//mes differentes consommations
copyleffe erazor 
Language Pompe Haute Pression (PHP)
 
WRInaute passionné
Blini a dit:
Pourquoi ne pas tout faire en une seule requête ? Ça éviterat des pbs, non ?
Code:
UPDATE utilisateur SET nbachats=nbachats+1 WHERE id='$idmembre' AND nbachats < 20
Et tu testes le retour pour voir s'il y a eu une mise à jour ou pas. Si nb_affected_rows = 0, c'est que le max a été atteint, et que l'update n'a donc rien fait.
Ça devrait repporter le pb d'accès concurrents sur la base SQL plutô que sur la page PHP...
Bon, à vérifier quand même, hein....

De fait, c'est de très loin la meilleure solution
 
Discussions similaires
Haut