Programmation concurrentielle PHP/MySQL - Comment faire?

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Programmation concurrentielle PHP/MySQL - Comment faire?

par delcedo galaxialord » 21 mars 2007, 01:37

Re Bonsoir !

Je viens de remarquer un élément intéressant avec la gestion du temps de PHP :
echo time()."<br />";
flush();
$db->lock(10); // pose un verrou avec un timeout de 10 secondes
echo time()."<br />";
flush();
sleep(5);
echo time()."<br />";
flush();
$db->unlock();
echo time()."<br />";
J'exécute deux instances de ce script et j'obtiens l'affichage suivant :
Thread 1 :

Code : Tout sélectionner

1174433666 1174433666 1174433671 1174433671
Thread 2 :

Code : Tout sélectionner

1174433671 1174433671 1174433676 1174433676
Les verrous fonctionnent très bien (parfait !), et le temps mis par les deux pages, selon PHP est de 5 secondes, alors que la durée constatée est pour première instance de 5 secondes et 10 secondes pour la seconde instance.

Quelqu'un aurait-il une explication ?

par delcedo galaxialord » 21 mars 2007, 00:53

Salut !

Ah merci :-) les GET_LOCK() resolvent mon problème. Je devais apparement mal les utiliser précédement !

Je ne peux/veux pas les mettre dans des UPDATE pour plusieurs raisons :
- j'utilise des fonctions génériques et faire une requête personnalisée juste pour faire un seul update sans mettre de verrous ne m'intéressait pas
- la requête aurait eu une taille trop grande à mon goût pour pouvoir garder une bonne lisibilité (je n'aime pas les instructions trop longues).
- j'ai des tests réalisés en PHP qui sont effectués entre la requête SELECT et la requête UPDATE. Certains de ces tests définissent si oui ou non la requête UPDATE sera exécutée ; la requête UPDATE deviendrait donc inutile et ne devrait donc pas être exécutée pour plus de sécurité.

Merci encore à vous deux pour m'avoir donné de votre temps afin de m'aider ! :D

Re: Programmation concurrentielle PHP/MySQL - Comment faire?

par Hubert Roksor » 20 mars 2007, 23:04

lock table (qui marche pas tout le temps chez moi j'ai l'impression)
Si tu fais le LOCK TABLE avant le SELECT ça devrait marcher, mais les performances risquent d'être désastreuse.

Tu dis vouloir éviter "UPDATE ... WHERE champ = champ + 1" à cause de tests que tu pratiquent, mais peut-être peux-tu mettre ces tests dans la requête UPDATE ? Décris un petit peu ces tests, quelqu'un aura peut-être une idée.

par sharep98 » 20 mars 2007, 18:14

Tu peux essayer de gérer les verrous au niveau applicatif en utilisant
GET_LOCK(), RELEASE_LOCK(), IS_FREE_LOCK() et IS_USED_LOCK().

Doc mySQL :
http://dev.mysql.com/doc/refman/5.0/en/ ... tions.html

Bon courage !

Programmation concurrentielle PHP/MySQL - Comment faire?

par delcedo galaxialord » 20 mars 2007, 17:20

Bonjour !

Je rencontre un problème en utilisant PHP et MySQL et je pense que la solution se trouve plutôt au niveau du serveur MySQL que de PHP et c'est pourquoi je poste donc dans cette partie plutôt que dans PHP.

Voici mon code PHP très simplifié :
<?php
// $db est un objet perso qui permet de faire des requêtes sql et de renvoyer immédiatement le résultat
$nbDeHit = $db->exec("SELECT value FROM globals WHERE label = 'nombreDeHit'");
$nbDeHit++; // ce qu'il faut retenir c'est qu'une modification est apportée à la variable 
sleep(rand(0,4000)); // et que cela dépend de condition qui ne peuvent pas être fait dans MySQL
$db->exec("UPDATE globals SET value = ".$nbDeHit." WHERE label = 'nombreDeHit'");
Le problème est donc si cette page est exécutée par plusieurs personnes en même temps, la valeur finale ne sera pas incrémenter de la somme des personnes, mais aura la valeur initial + 1.
Je ne veux pas de solution du genre : "UPDATE globals SET value = value + 1 WHERE label = 'nombreDeHit'" car j'effectue des tests sur la variable.

Quelles sont donc les solutions ? Est-il possible de faire des genres de mutex, lock table (qui marche pas tout le temps chez moi j'ai l'impression), ou tout autre meilleure solution ?

Merci beaucoup !