MongoDB 原子操作

  • 原子操作

    MongoDB不支持多文档原子事务。但是,它确实在单个文档上提供了原子操作。因此,如果文档有一百个字段,那么update语句将不更新所有字段或不更新任何字段,从而在文档级别上保持原子性。
  • 原子操作的模型数据

    保持原子性的推荐方法是保留所有相关信息,这些信息经常使用嵌入式文档在一个文档中一起更新。这样可以确保单个文档的所有更新都是原子的。假设我们创建了一个名称为productDetails的集合,并在其中插入了一个文档,如下所示-
    
    >db.createCollection("products")
    { "ok" : 1 }
    > db.productDetails.insert(
      {
        "_id":1,
        "product_name": "Samsung S3",
        "category": "mobiles",
        "product_total": 5,
        "product_available": 3,
        "product_bought_by": [
          {
            "customer": "john",
            "date": "7-Jan-2014"
          },
          {
            "customer": "mark",
            "date": "8-Jan-2014"
          }
        ]
      }
    )
    WriteResult({ "nInserted" : 1 })
    >
    
    在此文档中,我们将购买产品的客户的信息嵌入到product_bought_by字段中。现在,每当有新客户购买产品时,我们都会首先使用product_available字段检查该产品是否仍然可用。如果可用,我们将减少product_available字段的值,并将新客户的嵌入式文档插入product_bought_by字段。我们将使用findAndModify命令来实现此功能,因为它可以同时搜索和更新文档。
    
    >db.products.findAndModify({ 
       query:{_id:2,product_available:{$gt:0}}, 
       update:{ 
          $inc:{product_available:-1}, 
          $push:{product_bought_by:{customer:"rob",date:"9-Jan-2014"}} 
       }    
    })
    
    我们使用嵌入式文档并使用findAndModify查询的方法可确保仅在产品可用时才更新产品购买信息。整个交易都在同一查询中,是原子的。与此相反,请考虑以下情况:我们可能分别保留了产品的可用性和有关谁购买了该产品的信息。在这种情况下,我们将使用第一个查询首先检查该产品是否可用。然后在第二个查询中,我们将更新购买信息。但是,有可能在执行这两个查询之间,其他用户已经购买了该产品,而该产品不再可用。不知不觉中,我们的第二个查询将基于我们的第一个查询的结果更新购买信息。这将使数据库不一致,因为我们已经出售了不可用的产品。