TourDeJeu, le réseau des jeux en ligne alternatifs : jeux web multijoueurs, jeux par forum. En savoir +

Flux RSS des discussions du forum : pour les joueurs, et pour les créateurs et MJ
  Reply to this topicStart new topicStart Poll

> Verrouillage De Base De Donnée?, Comment éviter la connection simultanée
Manest
  Ecrit le : Samedi 11 Décembre 2004 à 22h55
Quote Post


Ouf
*

Groupe : Membre
Messages : 503


Voila, j'ai dans le code du jeu certains évenements qui s'active lors de la connection des joueurs.
Par exemple, un match dur une semaine, et bien la premiere personne qui va se connecter au match après la date de fin va provoquer l'arret du match.
Bon il peut y avoir plusieurs minute de décalage par moment, mais ce n'est pas vraiment génant.

Le problème est ailleurs.

En fait, il arrive que de nombreux joueurs soit connectés en même temps sur une page particulière, et dans notre cas de la fin du match par exemple, il est possible que ca la provoque deux fois (voir plus, on a eu 4 touchdown d'un coup une fois). Et c'est parfois très embetant.

Le problème c'est qu'il y a d'abord une condition (ex : match non fini?)
Si cette condition et vrai, le code rendre dans la partie de terminaison... mais si avant que celle ci soit fini un autre joueur débarque et passe la condition... bref s'il se connecte la même seconde... Ca execute le code deux fois...

Alors j'ai bien pensé à des trucs comme LOCK TABLES/UNLOCK TABLES mais je ne suis pas sûr que se soit l'ideal et je ne comprend pas bien comment ca fonctionne. Si la même action se produit et que la table est verrouillée, que va t'il se passer pour le second joueur? Message d'erreur?

Comment vous avez resolu le probleme?


--------------------
PMEmail PosterUsers Website
Top
Cedric
Ecrit le : Dimanche 12 Décembre 2004 à 00h43
Quote Post


Ouf
*

Groupe : Membre
Messages : 368


Tout d'abord, concernant les LOCK TABLE de MySQL : si une requete essaie d'acceder a une table lockee, elle attendra le UNLOCK... ce qui en general provoquera un timeout. Ca n'est donc pas terrible dans ton cas.
Il faut aussi savoir qu'il existe differents types de LOCK : WRITE/READ, Table-Level, Row-Level... Ca n'est pas forcemment tres simple a gerer mais c'est beaucoup plus souple.

Cela dit, j'aurais tendance a dire que dans ton cas ce n'est par contre pas une bonne solution. L'ideal me semblerait que tu stocke quelque part (dans une table annexe), le fait qu'une operation est en cours. Il faut ensuite que tu geres la situation en detectant le fait qu'une operation est deja en cours et que tu affiches un message pour le joueur. Ce n'est pas non plus tres simple car il faut vraiment le gerer proprement : il se peut que le joueur effectuant ton traitement de longue duree se deconnecte... et interrompe le traitement par exemple.
Dans ce cas il serait peut-etre plus simple d'utiliser un cron non ?

Enfin si ca peut te rassurer c'est un probleme assez courant.


--------------------
user posted image
PMEmail PosterUsers Website
Top
Merrick
Ecrit le : Mardi 21 Décembre 2004 à 15h45
Quote Post


Pro
*

Groupe : Membre
Messages : 57


Suis pas un spécialiste mysql, mais est ce que http://dev.mysql.com/doc/mysql/fr/InnoDB_locking_reads.html pourrait aider ?


--------------------
user posted image
PMEmail PosterUsers WebsiteICQ
Top
Nonothehobbit
Ecrit le : Mardi 21 Décembre 2004 à 20h41
Quote Post


Alien
*

Groupe : Moderateurs
Messages : 1298


Sinon pour la gestion de la concurrence, le mieux c'est d'utiliser les commit. (en gros on fait ses requêtes et on valide tout une fois les transactions terminées) Mais je ne sais pas si c'est supporté par mysql... unsure.gif


--------------------
user posted image
PMEmail PosterUsers Website
Top
gorgu
Ecrit le : Mercredi 22 Décembre 2004 à 05h34
Quote Post


Ouf
*

Groupe : Membre
Messages : 417


escuses moi mais c'est pas trés clair en fait....
tu fait des trucs et des fois c'est en doubles etc. enfin il est tard je suis peut etre fatigué


bon on va tenter

je suppose que tu as une page "match en cours" et qu'a chaque visite d'un joueur tu fais avancer le match d'une ou deux minutes.

et que de temps en temps le script php n'a pas le temps de ce finir et d'ajouter la fameuse minute qu'un autre visiteur fait recalculer la même minute de jeu.

total tu te retrouves dans ton compte rendu avec 4 but en 1 minute.

si c'est cela.

en premier lieu, oubli tout de suite les locks de table mysql, je penses que c'est pas adapté à une utilisation par php par un visiteur.

solution 1:

Ajout d'un minute au match dés le début de la page. il y aura peut etre 4 buts l'un derriere l'autre mais bon... plus dans la même minute.

solution 2:
<?
tu selectionnes le match select touttestrucs, actif from...
actif est un varchar 0 ou 1;
if actif==0
{
update champ calcul=1;

tu fais les calculs

tu update et remets calcul=0;
}
affichage de la page normale

?>
il existes un risque de blocage si par malheur php meurt pendant la page (cela arrivera de temps en temps si ton serveur est trop chargé).


--------------------
enfin je crois ...
Adept JDR
PMEmail PosterUsers Website
Top
Haiken
Ecrit le : Mercredi 22 Décembre 2004 à 13h46
Quote Post


Ouf
*

Groupe : Membre
Messages : 360


La solution idéale est d'utiliser les transactions (oui oui les commit, les locks sur lignes, tout ça...) mais ce n'est supporté pour MySQL qu'avec les tables au format innoDB.

Une solution de rechange est soit d'utiliser les locks classiques (LOCK TABLE) avec les problèmes que l'on connait (cela bloque toute la table), soit d'utiliser la solution de gorgu à un warning près :

CODE
tu selectionnes le match select touttestrucs, actif from...
actif est un varchar 0 ou 1;
if actif==0
{
update champ calcul=1;

tu fais les calculs

tu update et remets calcul=0;
}
affichage de la page normale


Il peut toujours arriver (avec une probabilité réduite, certes) que les calculs soient effectués en même temps par deux joueurs.

Ceux qui connaissent le principe des sémaphores connaissent sûrement les méthodes P() et V() (sinon c'est le moment de se documenter wink.gif
Il faut une exclusion mutuelle !

Pour émuler ça avec quasi rien, on peut utiliser un table de verrous avec un seul champ texte "nom_verrou" (mis comme index)

l'operation de verrouillage est alors :
function verrouiller($nom) {
$r=mysql_query("replace into verrous values ('$nom')");
return mysql_affected_rows($r)!=1; //1 = insert, 2 = remplacement (delete+insert)
}

function liberer($nom) {
$r=mysql_query("delete from verrous where nom_verrou='$nom'");
}

Le code de gorgu donne alors :
QUOTE
tu selectionnes le match select touttestrucs from...
if (verrouiller($numero_match)) {
{
tu fais les calculs

liberer($numero_match)
affichage de la page normale
} else {
afficher("Match en cours de calcul, revenez un peu plus tard")
}


il existe par contre aussi toujours l'histoire du blocage, mais on peut imaginer de mettre un timeout sur un verrou


--------------------
PMEmail Poster
Top
« Sujets + anciens | Programmer | Sujets + récents »

Reply to this topicStart new topicStart Poll