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
Candidat au titre de Membre du Club
 
Inscription : octobre 2006
Messages : 45
Détails du profil
Informations personnelles :
Localisation : Suisse

Informations forums :
Inscription : octobre 2006
Messages : 45
Points : 11
Points : 11
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 :
1
2
3
4
5
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 00
Vieux 04/02/2010, 14h25   #2
Modérateur
 
Avatar de sabotage
 
Homme Vincent
Inscription : juillet 2005
Messages : 14 929
Détails du profil
Informations personnelles :
Nom : Homme Vincent

Informations forums :
Inscription : juillet 2005
Messages : 14 929
Points : 16 381
Points : 16 381
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 00
Vieux 05/02/2010, 07h57   #3
Candidat au titre de Membre du Club
 
Inscription : octobre 2006
Messages : 45
Détails du profil
Informations personnelles :
Localisation : Suisse

Informations forums :
Inscription : octobre 2006
Messages : 45
Points : 11
Points : 11
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 00
Vieux 05/02/2010, 08h24   #4
Expert Confirmé
 
Avatar de RunCodePhp
 
Inscription : janvier 2010
Messages : 2 238
Détails du profil
Informations personnelles :
Localisation : Réunion

Informations forums :
Inscription : janvier 2010
Messages : 2 238
Points : 2 591
Points : 2 591
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.2 | Apache 2.2.21 | Php 5.3.8 | MySQL 5.5.16
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 00
Vieux 05/02/2010, 08h28   #5
Candidat au titre de Membre du Club
 
Inscription : octobre 2006
Messages : 45
Détails du profil
Informations personnelles :
Localisation : Suisse

Informations forums :
Inscription : octobre 2006
Messages : 45
Points : 11
Points : 11
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 00
Vieux 05/02/2010, 08h34   #6
Expert Confirmé
 
Avatar de RunCodePhp
 
Inscription : janvier 2010
Messages : 2 238
Détails du profil
Informations personnelles :
Localisation : Réunion

Informations forums :
Inscription : janvier 2010
Messages : 2 238
Points : 2 591
Points : 2 591
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.2 | Apache 2.2.21 | Php 5.3.8 | MySQL 5.5.16
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 00
Vieux 05/02/2010, 08h35   #7
Candidat au titre de Membre du Club
 
Inscription : octobre 2006
Messages : 45
Détails du profil
Informations personnelles :
Localisation : Suisse

Informations forums :
Inscription : octobre 2006
Messages : 45
Points : 11
Points : 11
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 00
Vieux 05/02/2010, 08h40   #8
Expert Confirmé
 
Avatar de RunCodePhp
 
Inscription : janvier 2010
Messages : 2 238
Détails du profil
Informations personnelles :
Localisation : Réunion

Informations forums :
Inscription : janvier 2010
Messages : 2 238
Points : 2 591
Points : 2 591
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.2 | Apache 2.2.21 | Php 5.3.8 | MySQL 5.5.16
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 00
Vieux 05/02/2010, 08h40   #9
Candidat au titre de Membre du Club
 
Inscription : octobre 2006
Messages : 45
Détails du profil
Informations personnelles :
Localisation : Suisse

Informations forums :
Inscription : octobre 2006
Messages : 45
Points : 11
Points : 11
Ok, je vais voir ça.

merci beaucoup !
NeqO55 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/02/2010, 09h01   #10
Modérateur
 
Avatar de sabotage
 
Homme Vincent
Inscription : juillet 2005
Messages : 14 929
Détails du profil
Informations personnelles :
Nom : Homme Vincent

Informations forums :
Inscription : juillet 2005
Messages : 14 929
Points : 16 381
Points : 16 381
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 00
Vieux 05/02/2010, 09h04   #11
Candidat au titre de Membre du Club
 
Inscription : octobre 2006
Messages : 45
Détails du profil
Informations personnelles :
Localisation : Suisse

Informations forums :
Inscription : octobre 2006
Messages : 45
Points : 11
Points : 11
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 00
Vieux 05/02/2010, 09h36   #12
Modérateur
 
Avatar de sabotage
 
Homme Vincent
Inscription : juillet 2005
Messages : 14 929
Détails du profil
Informations personnelles :
Nom : Homme Vincent

Informations forums :
Inscription : juillet 2005
Messages : 14 929
Points : 16 381
Points : 16 381
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 00
Vieux 05/02/2010, 09h38   #13
Candidat au titre de Membre du Club
 
Inscription : octobre 2006
Messages : 45
Détails du profil
Informations personnelles :
Localisation : Suisse

Informations forums :
Inscription : octobre 2006
Messages : 45
Points : 11
Points : 11
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 00
Vieux 05/02/2010, 10h13   #14
Modérateur
 
Avatar de sabotage
 
Homme Vincent
Inscription : juillet 2005
Messages : 14 929
Détails du profil
Informations personnelles :
Nom : Homme Vincent

Informations forums :
Inscription : juillet 2005
Messages : 14 929
Points : 16 381
Points : 16 381
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 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +1. Il est actuellement 04h09.


 
 
 
 
Partenaires

Hébergement Web