2012-05-28 3 views
-2

je veux mettre à jour certaines données dans MongoDB, ma logique est la suivante:comment éviter la condition de course mongodb

#find the specific document with "md5,time,size", 
if collection.find({"src_md5":file_md5,"src_time":file_time,"src_size":file_size}).count() == 0: 
    #if not found 
    # find the idx,if idx is not yet exist,set idx equa 1 

    if collection.find({},{"idx":1}).count() == 0: 
     idx = 1 

    #if idx is alread there, sort idx and get the biggest idx 
    else: 
     idx = collection.find({},{"idx":1}).sort('idx',-1).limit(5)[0]['idx'] 
     idx = idx + 1 

     #insert the info with idx 
     if not self.insertFileInfo(collection,file_obj,file_md5,file_time,file_size,long(idx)): 
      return None 
#if the specific document with "md5,time,size" is found 
else: 
#just get the idx with the specific md5 
    idx = collection.find({"src_md5":file_md5,"src_time":file_time,"src_size":file_size},{"idx":1})[0]['idx'] 
    return None 

je vais exécuter le code ci-dessus dans 4 machines, ce qui signifie 4 processus mettrait à jour mongodb presque simultanément, comment puis-je assurer l'atomique des opérations? mon schéma recored est

{"src_md5":"djapijfdakfiwqjfkasdj","src_size":2376498,"src_time":1338179291,"idx":1} 
{"src_md5":"jdfipajkoijjipjefjidwpj","src_size":234876323,"src_time":1338123873,"idx":2} 
{"src_md5":"djapojfkdasxkjipkjkf","src_size":3829874,"src_time":1338127634,"idx":3} 

ce n'est pas une simple clé d'incrémentation automatique, il doit être augmentée si md5, la taille, le temps a changé, et shuld être insérer avec eux, comme un record. Je crée un index unique composé sur {"src_md5", "src_time", "src_size"}, et crée un index unique sur {"idx"}, mais avant d'insérer de nouvelles informations, je devrais avoir l'idx alread existant, alors augmente-le. il y a deux cas: 1, IDX avec le md5 spécifique, la taille, le temps, s'est déjà exister, juste retour l'IDX 2, sinon exister, augmenter IDX avec 1

+0

Il semble que votre code renvoie Aucun sur tous les chemins. Est-ce une faute de frappe? –

+0

sont ces quatre champs les seuls champs dans le document? sont ces attributs d'un fichier qui a d'autres attributs (comme un nom de fichier ou quelque chose de similaire?) –

Répondre

1

Un problème similaire est discuté dans ce question. Ce que vous voulez faire est similaire à avoir une clé monotone croissante unique que vous garderiez dans sa propre collection et incrémenter en utilisant $ inc comme décrit dans la question liée. Ceci garantira que vous n'essaierez jamais d'utiliser deux fois le même idx. Maintenant, il est toujours possible que deux threads essaient d'insérer une nouvelle combinaison de (md5, size, time) avec deux clés idx différentes, mais la seconde échouera en raison de l'index unique que vous avez (md5, size, time) . La seule condition de concurrence qui existe ici est lorsque le deuxième thread ne parvient pas à insérer en raison de l'index unique, vous vous retrouverez avec une valeur idx inutilisée (à chaque fois que cela arrive, l'augmentation des valeurs idx en ignorera une). Quelle est la taille d'un problème pour vous? Si vous avez une taille importante, vous devrez soit verrouiller le code de votre application, soit modifier la structure de votre schéma pour traiter ce cas.

Questions connexes