Précédent   Forum des professionnels en informatique > PHP > PHP & SGBD > PHP & MySQL
PHP & MySQL Forum d'entraide sur les fonctions MySQL avec PHP. Avant de poster -> FAQ MySQL, Cours MySQL et Sources MySQL. Pour les questions concernant le moteur MySQL plutôt que les fonctions PHP, merci d'utiliser le forum MySQL.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
Vieux 04/02/2010, 13h48   #1
Futur Membre du Club
 
Date d'inscription: octobre 2006
Localisation: Suisse
Messages: 36
Par défaut Requête bloquante en MySQL (transactions?)

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");
Est-ce que cette façon de faire est correcte? Surtout, est-ce qu'elle me garanti que deux clients ne recevront pas les mêmes enregistrements?

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.
NeqO55 est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 04/02/2010, 14h25   #2
Modérateur
 
Avatar de sabotage
 
Date d'inscription: juillet 2005
Messages: 10 088
Par défaut

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;
sabotage est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 05/02/2010, 07h57   #3
Futur Membre du Club
 
Date d'inscription: octobre 2006
Localisation: Suisse
Messages: 36
Par défaut

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?
NeqO55 est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 05/02/2010, 08h24   #4
Membre éprouvé
 
Avatar de RunCodePhp
 
Date d'inscription: janvier 2010
Localisation: Ile De La Réunion
Messages: 413
Par défaut

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]
RunCodePhp est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 05/02/2010, 08h28   #5
Futur Membre du Club
 
Date d'inscription: octobre 2006
Localisation: Suisse
Messages: 36
Par défaut

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?
NeqO55 est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 05/02/2010, 08h34   #6
Membre éprouvé
 
Avatar de RunCodePhp
 
Date d'inscription: janvier 2010
Localisation: Ile De La Réunion
Messages: 413
Par défaut

Citation:
Tu m'embrouilles un peu là, il vaut mieux utiliser LOCK TABLES ou les transactions, puisqu'apparemment cela fait la même chose?
Désolé pour l'embrouille

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]
RunCodePhp est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 05/02/2010, 08h35   #7
Futur Membre du Club
 
Date d'inscription: octobre 2006
Localisation: Suisse
Messages: 36
Par défaut

J'utilise InnoDB.

Je peux donc faire une transaction comme expliqué dans mon premier post sans avoir de problèmes?
NeqO55 est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 05/02/2010, 08h40   #8
Membre éprouvé
 
Avatar de RunCodePhp
 
Date d'inscription: janvier 2010
Localisation: Ile De La Réunion
Messages: 413
Par défaut

Citation:
Envoyé par NeqO55 Voir le message
Je peux donc faire une transaction comme expliqué dans mon premier post sans avoir de problèmes?
Normalement oui.

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]
RunCodePhp est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 05/02/2010, 08h40   #9
Futur Membre du Club
 
Date d'inscription: octobre 2006
Localisation: Suisse
Messages: 36
Par défaut

Ok, je vais voir ça.

merci beaucoup !
NeqO55 est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 05/02/2010, 09h01   #10
Modérateur
 
Avatar de sabotage
 
Date d'inscription: juillet 2005
Messages: 10 088
Par défaut

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.
sabotage est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 05/02/2010, 09h04   #11
Futur Membre du Club
 
Date d'inscription: octobre 2006
Localisation: Suisse
Messages: 36
Par défaut

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 :/
NeqO55 est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 05/02/2010, 09h36   #12
Modérateur
 
Avatar de sabotage
 
Date d'inscription: juillet 2005
Messages: 10 088
Par défaut

Reprend la requête que je t'ai fourni au début : elle traite les lignes et indique qu'elles ont été traitées.
sabotage est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 05/02/2010, 09h38   #13
Futur Membre du Club
 
Date d'inscription: octobre 2006
Localisation: Suisse
Messages: 36
Par défaut

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 ?
NeqO55 est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 05/02/2010, 10h13   #14
Modérateur
 
Avatar de sabotage
 
Date d'inscription: juillet 2005
Messages: 10 088
Par défaut

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.
sabotage est déconnecté   Envoyer un message privé Réponse avec citation
NEWS PHPFAQ PHPCours PHPSources PHPLivres PHPScripts PHPOutils PHPComparatifsZend Framework

Réponse Proposer ce sujet en actualité

Précédent   Forum des professionnels en informatique > PHP > PHP & SGBD > PHP & MySQL



Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are non
Pingbacks are non
Refbacks are non



Fuseau horaire GMT +1. Il est actuellement 00h30.


Vos questions techniques : forum d'entraide PHP - Publiez vos articles, tutoriels et cours
et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones
Nous contacter - Hébergement - Participez - Copyright © 2000-2010 www.developpez.com - Legal informations.