2009-07-08 7 views
1

J'ai des travailleurs multiples SELECTing et UPDATing row.MYSQL Comment puis-je m'assurer que la ligne n'est pas mise à jour plus d'une fois?

état id 10 nouveaux 11 nouveaux 12 vieux 13 vieux

travailleur choisit une 'nouvelle' ligne et met à jour son statut 'ancien'. Et si deux travailleurs sélectionnaient la même rangée en même temps? Je veux dire que worker1 sélectionne une nouvelle ligne, et avant que le worker 1 ne mette à jour son statut, worker2 sélectionne la même ligne?

Devrais-je sélectionner et mettre à jour dans une requête ou existe-t-il un autre moyen?

Répondre

2

Vous pouvez verrouiller la table avant votre lecture, et le déverrouiller après votre écriture. Cela éliminerait la possibilité pour deux travailleurs de mettre à jour le même enregistrement en même temps.

http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html

+0

un verrouillage empêche la lecture/SELECT? Si je peux encore choisir, je pourrais utiliser le concept @daremon mentionné ci-dessous. –

+1

Si vous faites un verrou WRITE, toutes les autres sessions se bloqueront en essayant de lire ou d'écrire. – Pro777

0

Selon votre moteur de stockage de base de données (InnoDB, MyISAM, etc.), vous pouvez être en mesure de verrouiller la table alors qu'une personne est modifing elle. Il garderait alors des actions simotanious à la même table.

0

pourriez-vous mettre des conditions dans votre logique PHP pour impliquer un verrou? Comme définir un attribut d'état sur une ligne qui empêcherait le deuxième utilisateur d'effectuer une mise à jour. Cela nécessiterait éventuellement d'interroger la base de données avant une mise à jour pour s'assurer que la ligne n'est pas verrouillée.

+0

L'interrogation de la base de données juste avant la mise à jour n'est pas une bonne protection de la concurrence: elle peut être mise à jour entre les deux. –

3

Vous pouvez utiliser LOCK TABLES mais parfois je préfère la solution (en pseudo-code) suivant:

// get 1 new row 
$sql = "select * from table where status='new' limit 0, 1"; 
$row = mysql_query($sql); 

// update it to old while making sure no one else has done that 
$sql = "update table set status='old' where status='new' and id=row[id]"; 
mysql_query($sql); 

// check 
if (mysql_affected_rows() == 1) 
    // status was changed 
else 
    // failed - someone else did it 
+0

Ce que vous avez fait dans votre code est aussi ce que j'ai fait. Je ne pense pas que ce soit le plus efficace mais c'est simple et ça marche. Je vous remercie! –

Questions connexes