Mongodb 简明教程

MongoDB - Atomic Operations

Model Data for Atomic Operations

推荐的原子性维护方法是将所有相关信息保存在使用 embedded documents 的单文档中,该文档经常一起更新。这将确保针对单文档的所有更新都是原子的。

The recommended approach to maintain atomicity would be to keep all the related information, which is frequently updated together in a single document using embedded documents. This would make sure that all the updates for a single document are atomic.

假设我们已创建一个名为 productDetails 的集合,并按如下所示在集合中插入文档:

Assume we have created a collection with name productDetails and inserted a documents in it as shown below −

>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 命令,因为它在同一执行步骤中搜索并更新文档。

In this document, we have embedded the information of the customer who buys the product in the product_bought_by field. Now, whenever a new customer buys the product, we will first check if the product is still available using product_available field. If available, we will reduce the value of product_available field as well as insert the new customer’s embedded document in the product_bought_by field. We will use findAndModify command for this functionality because it searches and updates the document in the same go.

>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 查询可确保仅在产品可用时才会更新产品购买信息。而且,这项事务的全部内容都在同一查询中,是原子的。

Our approach of embedded document and using findAndModify query makes sure that the product purchase information is updated only if it the product is available. And the whole of this transaction being in the same query, is atomic.

与之相反,考虑一下可能将产品可用性和关于谁已购买该产品的信息分开保存的情况。在这种情况下,我们将首先使用第一个查询检查产品是否可用。然后,在第二个查询中,我们将更新购买信息。然而,在执行这两个查询的过程中,另一些用户可能已购买该产品,而产品已不再可用。在不知道这种情况之下,我们的第二个查询将根据第一个查询的结果更新购买信息。这将使数据库不一致,因为我们已销售了不可用的产品。

In contrast to this, consider the scenario where we may have kept the product availability and the information on who has bought the product, separately. In this case, we will first check if the product is available using the first query. Then in the second query we will update the purchase information. However, it is possible that between the executions of these two queries, some other user has purchased the product and it is no more available. Without knowing this, our second query will update the purchase information based on the result of our first query. This will make the database inconsistent because we have sold a product which is not available.