IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes MySQL Discussion :

Problème de concurrence sur table InnoDB


Sujet :

Requêtes MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Septembre 2013
    Messages : 14
    Par défaut Problème de concurrence sur table InnoDB
    Bonjour à tous,

    J'écris en PHP un jeu d'instant gagnant dans lequel il est possible de gagner une fois toutes les demi heures. Pour ce faire, je vérifie dans ma table "winnertable" l'heure du dernier gain (SELECT), et si cela remonte à plus d'une demi-heure, j'insère le nouveau gagnant (INSERT).

    Ma table winnertable est sous InnoDB.

    Cette partie de mon script est appelée par chaque client et décide si il a gagné ou non. La réponse doit lui être affichée à la page suivante, donc pas possible de mettre en place un CRON.

    Voici ce que cela donne en pseudo code (version PHP ici : http://pastebin.com/dn1txbYm) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT date FROM winnertable ORDER BY id DESC
    Si (la date actuelle) - (le champ "date" de la première ligne renvoyée par la requête précédente) > une demi-heure alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    INSERT INTO winnertable (id_main, date) VALUES ('".$_SESSION['id']."', '".$currentTime."')
    Je pense que cette solution n'est pas bonne car si le script est lu par de multiples clients au même moment, des SELECT risquent d'être exécutés au même moment et plusieurs clients risquent alors de gagner à chaque demi-heure.

    J'ai cherché quelques solutions :
    • Utiliser un LOCK TABLE : mais j'ignore le coût en termes de performances. De plus, j'ai lu que c'était déconseillé de le faire sur une table InnoDB. Je peux cependant passer ma table en MyIsam si c'est la solution.
    • Rendre mon champ "date" UNIQUE en base, pour éviter de multiples insertions de la même date. Mais je ne suis pas sur que ce soit fiable à 100%.
    • Utiliser les transactions d'InnoDB, mais je ne suis pas certain du tout que les transactions empêchent les accès concurrents en lecture ou en écriture. Sur le web beaucoup de ressources parlent du SELECT FOR UPDATE, mais en l'occurrence, je fais plutot un SELECT puis INSERT en fonction, donc je ne m'y retrouve pas.


    Qu'en pensez-vous ?

    Merci !

  2. #2
    Membre habitué
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Septembre 2013
    Messages : 14
    Par défaut
    Je viens d'avoir une idée :

    Est-ce que ce ne serait pas mieux d'insérer directement tout le monde dans la table des gagnants, puis de sélectionner ensuite le gagnant par ordre d'insertion des ID ? Quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    INSERT INTO participants (date, id_main) VALUE (:current_date, :id_main)
    Puis la requête suivante pour retrouver le dernier gagnant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT date FROM participants WHERE win=1 ORDER BY ID DESC
    Puis calculer en PHP si la date > 1/2h

    Et si oui {
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT id, id_main FROM participants WHERE date = :current_date ORDER BY id ASC
    Et sur le résultat de la requète précédente :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE participants SET win=1 WHERE id=:id
    }

    Il pourrait y avoir plusieurs requêtes concurrentes toutes les demi heures, mais elles donneraient toutes le même résultat, non ?

Discussions similaires

  1. Problème tri permanent sur table
    Par satane dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 28/11/2010, 08h58
  2. problème de contrainte avec tables INNODB
    Par diblasio dans le forum Débuter
    Réponses: 3
    Dernier message: 19/08/2010, 16h09
  3. Effacement de colonne impossible sur table InnoDB volumineuse
    Par jvanbouc dans le forum Administration
    Réponses: 11
    Dernier message: 14/01/2010, 16h04
  4. Probléme de concurrence sur une table
    Par D_light dans le forum Administration
    Réponses: 2
    Dernier message: 03/03/2008, 13h14
  5. Problème de filtre sur table
    Par omega dans le forum Langage SQL
    Réponses: 4
    Dernier message: 11/08/2006, 10h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo