|
Publicité | ||||||||||||||||||||||
|
|
#1 |
|
Futur Membre du Club
![]() Date d'inscription: octobre 2006
Localisation: Suisse
Messages: 36
|
Bonjour,
J'ai lu pas mal de threads ici et ailleurs, mais je ne suis pas convaincu que ce que compte faire est correct. Mon problème est simple. Je veux récupérer les enregistrements qui ne sont pas notés comme "traités" puis les noter comme traités. Il y a bien sûr un problème de concurrence, pour ne pas donner des enregistrements non traités à deux clients différents. mon idée de base est Code :
mysqli_query("start transaction"); mysqli_query("select ... from ... where `processed` = 0"); // Traitement des données du select mysqli_query("update set `processed` = 1 where `processed` = 0"); mysqli_query("commit"); Je n'ai jamais travaillé avec de la concurrence en base de données et je ne suis pas très sûr que c'est cela fonctionne ainsi. merci de votre aide edit: modification du code pour meilleure compréhension Dernière modification par NeqO55 ; 05/02/2010 à 07h59. |
|
|
|
|
|
#2 |
![]() Date d'inscription: juillet 2005
Messages: 10 088
|
Le SELECT avant l'UPDATE n'a aucun effet.
Il n'y a de toute facon pas de concurrence dans ton cas : ta ligne à un moment donné vaut soit 0 soit 1. Code sql :
UPDATE TABLE SET client='toto', processed= 1 WHERE processed=0; |
|
|
|
|
|
#3 |
|
Futur Membre du Club
![]() Date d'inscription: octobre 2006
Localisation: Suisse
Messages: 36
|
Si je fais un select, c'est parce que je veux connaitre les elements qui ne sont pas processed !
Mon probleme est que si deux processus différents s'executent process1: select... process2: select... process1: update... process2: update... process1: traitement des données process2: traitement des données Dans ce cas les données seront traitées deux fois, c'est justement ce que je veux éviter! Ou alors j'ai mal compris ce que tu as dit? |
|
|
|
|
|
#4 |
|
Membre éprouvé
![]() Date d'inscription: janvier 2010
Localisation: Ile De La Réunion
Messages: 413
|
Salut
Peut être voir du coté de LOCK TABLES / UNLOCK TABLES que les transactions. Ceci dit, et si je ne dis pas de bêtise, une transaction c'est fait justement pour éviter la concurrence, ça revient au même que de bloquer les tables. Donc normalement il n'y a pas besoin de t'appuyer sur une donnée de la Bdd comme ton champ processed. En fait, on dirait que tu es en train de créer toi même ton propre système de processus. Si tu as une succession de SQL à faire et qu'ils ne doivent pas être perturbés, tu les regroupe dans 1 transaction, cela va verrouiller les tables concernées, il y aura une file d'attente si un autre processus tente d'interroger les mêmes tables. Enfin, c'est ce que j'ai retenu des transactions. Le scénario que tu a mis est théoriquement impossible, le processus2 (plutôt transaction) attendra que le le 1er finisse. Enfin, si j'ai bien compris ton problème.
__________________
Win XP | WampServer 2.0 | Apache 2.2.11 | Php 5.3.0 | MySQL 5.1.36 Si debugger, c’est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra] |
|
|
|
|
|
#5 |
|
Futur Membre du Club
![]() Date d'inscription: octobre 2006
Localisation: Suisse
Messages: 36
|
Merci pour ta réponse.
Mon champ "processed" a d'autres utilités dans le code, il n'est pas là uniquement pour effectuer un blocage. Tu m'embrouilles un peu là, il vaut mieux utiliser LOCK TABLES ou les transactions, puisqu'apparemment cela fait la même chose? |
|
|
|
|
|
#6 | |
|
Membre éprouvé
![]() Date d'inscription: janvier 2010
Localisation: Ile De La Réunion
Messages: 413
|
Citation:
Ca dépend du moteur de MySQL que tu utilise. Tu ne pourras pas faire de transaction avec le moteur MyISAM, utiliser les LOCK TABLES deviens la seule manière d'éviter la concurrence, cela simule une transaction. Si tu veux utiliser les transactions (commit / rollback), faut utiliser le moteur InnoDB. Attention cependant concernant les hébergeurs mutualisés, car même s'ils autorisent l'utilisation de InnoDB, certains ne peuvent pas garantir une sauvegarde complètes de la Bdd. Ca peut avoir son importance.
__________________
Win XP | WampServer 2.0 | Apache 2.2.11 | Php 5.3.0 | MySQL 5.1.36 Si debugger, c’est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra] |
|
|
|
|
|
|
#7 |
|
Futur Membre du Club
![]() Date d'inscription: octobre 2006
Localisation: Suisse
Messages: 36
|
J'utilise InnoDB.
Je peux donc faire une transaction comme expliqué dans mon premier post sans avoir de problèmes? |
|
|
|
|
|
#8 | |
|
Membre éprouvé
![]() Date d'inscription: janvier 2010
Localisation: Ile De La Réunion
Messages: 413
|
Citation:
Il te faut quand même bien implanter ton code de façon que s'il y a erreur pendant le traitement, derrière il y aura un rollback, sinon ???
__________________
Win XP | WampServer 2.0 | Apache 2.2.11 | Php 5.3.0 | MySQL 5.1.36 Si debugger, c’est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra] |
|
|
|
|
|
|
#9 |
|
Futur Membre du Club
![]() Date d'inscription: octobre 2006
Localisation: Suisse
Messages: 36
|
Ok, je vais voir ça.
merci beaucoup ! |
|
|
|
|
|
#10 |
![]() Date d'inscription: juillet 2005
Messages: 10 088
|
J'insiste mais ce que tu fais ne sert a rien
si tu fais WHERE processed=0 tu ne traiteras que les lignes que tu veux. |
|
|
|
|
|
#11 |
|
Futur Membre du Club
![]() Date d'inscription: octobre 2006
Localisation: Suisse
Messages: 36
|
Oui mais il faut bien que je garde une trace des éléments qui ont déjà été traités, non ?
Sans parler de concurrence, imagine qu'un process est relancé 3 jours après. Je ne veux pas que ces éléments soient traités, puisqu'ils ont étés traités 3 jours plus tôt. Chaque élément doit être traité une et une seule fois, à vie. J'ai sûrement mal compris ce que vous essayez de me faire comprendre :/ |
|
|
|
|
|
#12 |
![]() Date d'inscription: juillet 2005
Messages: 10 088
|
Reprend la requête que je t'ai fourni au début : elle traite les lignes et indique qu'elles ont été traitées.
|
|
|
|
|
|
#13 |
|
Futur Membre du Club
![]() Date d'inscription: octobre 2006
Localisation: Suisse
Messages: 36
|
Moi je veux connaitre le contenu de ces lignes.
La méthode UPDATE ne permet pas de connaitre le contenu, juste de le modifier, non ? |
|
|
|
|
|
#14 |
![]() Date d'inscription: juillet 2005
Messages: 10 088
|
Hum ... tu peux alors
1 - mettre tes lignes "en cours de traitement" 2 - faire le SELECT sur ce statut 3 - réaliser le traitement 4 - mettre les lignes traitées en "traitées" Pour moi la transaction n'apporte rien en tout cas : l'idée de la transaction c'est "tout le traitement est réalisé ou sinon on annule". La gestion des Locks est possible, mais en php ce n'est pas forcemment evident non plus. |
|
|
|
|
|
![]() |
||
Requête bloquante en MySQL (transactions?)
|
||
| Outils de la discussion | |
|
|