2013-05-02 2 views
1

J'ai un problème avec les mises à jour de mongo dans mon projet actuel. Nous avons un pool de documents maintenu dans MongoDB. Un processus de lecture récupère un lot de documents de ce pool. Afin de s'assurer que les documents de la base de données ne sont pas récupérés à nouveau, un statut associé à chaque document est modifié (par exemple, de Arrivé à Traitement). Nous envisageons de mettre à l'échelle et d'avoir de multiples processus de lecture en sélectionnant différents lots. Cependant, selon ce que je crois savoir, les mises à jour de mongo ne sont pas atomiques sur le lot.Est-ce que je peux y arriver? pour s'assurer qu'un document ne soit pas récupéré du pool par un lecteur différent avant d'être mis à jour par le précédent. Je regarde essentiellement les mises à jour atomiques par lots. Merci!Est-il possible d'avoir des mises à jour atomiques par lots dans MongoDB?

Répondre

1

On peut supposer que vous faites quelque chose comme ça pour mettre à jour la statue:

db.docs.update({status:"arrived"},{$set:{status:"processing"}},{multi:true}) 

suivi par une charge des documents ayant un statut: « traitement ».

Il n'y a actuellement aucune incantation mongo pour mettre à jour plus d'un mais moins que tous les documents correspondants. Vous utilisez {multi:true} pour tous les documents ou vous ne marquez qu'un seul document. Par conséquent, vous pouvez essayer de marquer les documents arrivants avec un identifiant unique pour chaque processus de lecture avec une mise à jour non multi-utilisateur. Lisez ensuite le document à traiter. Le marquage met à jour atomiquement un document avec l'identifiant unique d'un lecteur, évitant ainsi les conflits entre les lecteurs.

Quelque chose comme:

db.docs.update({status:"arrived"},{$set:{status:"processing", readerId:<myid>}}) 

<myid> est l'identifiant unique pour le processus de lecteur qui émet cette mise à jour mongo.

Ensuite, le lecteur peut charger docs avec: db.docs.find({status:"processing", readerId:<myid>}}

+0

Merci pour la réponse mais je ne pense pas que cela résoudrait le problème. Mon problème est que je veux que les statuts de tous les documents d'un lot soient changés atomiquement et l'ajout d'un lecteur ne semble pas gérer ce problème. – Tazo

+0

Avec le comportement un-ou-tout de la mise à jour, vous avez une taille de lot de un lors du marquage ou tous les nouveaux documents iront à un lecteur. – grogers

+0

Lors d'une deuxième lecture de http://docs.mongodb.org/manual/faq/concurrency/, je dirais que ce n'est pas du tout clair si le résultat est différent lorsque plusieurs threads émettent une instruction de mise à jour avec la même requête. Les threads seraient en concurrence pour les documents et tout dépendrait du thread qui obtient le verrou d'écriture après un rendement. Il y a un problème ouvert sur mongo pour supporter la mise à jour avec limite: https://jira.mongodb.org/browse/SERVER-1599. – grogers

0

Si vous utilisez findAndModify vous pouvez trouver et mettre à jour atomiquement un document.

Si vous

db.docs.findAndModify({ 
    query : {'status':'arrived' }, 
    sort: { dateTimeOfdoc:-1}, 
    update : { 'status':'processing','transactionId':12345}, 
    new : true}); 

Alors que toutes les discussions sont en concurrence pour les documents, parce que chaque document peut être trouvé et modifié dans une opération atomique, cela signifie une fois un fil a, il ne sera pas en alla chercher par d'autres.

Ce n'est pas un lot de docs comme vous le vouliez, mais est-ce que cela résout votre problème?

Questions connexes