MongoDB - 原子操作

MongoDB不支持多文档原子事务.但是,它确实在单个文档上提供原子操作.因此,如果文档有100个字段,则更新语句将更新所有字段或不更新,因此在文档级别保持原子性.

原子操作的模型数据

维护原子性的推荐方法是保留所有相关信息,这些信息经常使用嵌入文档在一个文档中一起更新.这将确保单个文档的所有更新都是原子的.

考虑以下产品文档 :

{
   "_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"
      }
   ]
}


在本文档中,我们在 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查询确保只有在产品可用时才更新产品购买信息.并且整个此事务处于同一查询中,是原子的.

与此相反,请考虑我们可能保留产品可用性的情况以及有关谁购买了该产品的信息.产品,分开.在这种情况下,我们将首先使用第一个查询检查产品是否可用.然后在第二个查询中,我们将更新购买信息.但是,在这两个查询的执行之间,某些其他用户可能已经购买了该产品并且它不再可用.在不知情的情况下,我们的第二个查询将根据我们的第一个查询结果更新购买信息.这将使数据库不一致,因为我们已经销售了一个不可用的产品.