Mongodb-atomic-operations

提供:Dev Guides
移動先:案内検索

MongoDB-アトミックオペレーション

MongoDBは*マルチドキュメントアトミックトランザクション*をサポートしていません。 ただし、単一のドキュメントに対してアトミック操作を提供します。 そのため、ドキュメントに100個のフィールドがある場合、更新ステートメントはすべてのフィールドを更新するか、まったく更新しないため、ドキュメントレベルで原子性が維持されます。

原子操作のモデルデータ

原子性を維持するための推奨アプローチは、すべての関連情報を保持することです。これは、*埋め込み文書*を使用して単一の文書で頻繁に更新されます。 これにより、1つのドキュメントのすべての更新がアトミックになります。

以下に示すように、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クエリを使用するアプローチにより、製品が利用可能な場合にのみ、製品購入情報が更新されます。 そして、同じトランザクション内にあるこのトランザクション全体はアトミックです。

これとは対照的に、製品の可用性と製品を購入したユーザーに関する情報を別々に保持するシナリオを検討してください。 この場合、最初のクエリを使用して、製品が利用可能かどうかを最初に確認します。 次に、2番目のクエリで購入情報を更新します。 ただし、これら2つのクエリの実行の間に、他のユーザーが製品を購入し、使用できなくなる可能性があります。 これを知らなくても、2番目のクエリは最初のクエリの結果に基づいて購入情報を更新します。 利用できない製品を販売しているため、これによりデータベースの一貫性が失われます。