MongoDB不支援多文件原子事務。 但是,它可以為單個文件提供了原子操作。 因此,如果文件有一百個欄位,則更新語句將更新或不更新所有欄位的值,因此在原始級別保持原子性。
維持原子性的推薦方法是將所有相關資訊儲存在一起,並使用嵌入式文件在一個文件中一起更新。 這將確保單個文件的所有更新都是原子的。
考慮以下產品檔案 -
{
"_id":1,
"product_name": "Huawei P9",
"category": "mobiles",
"product_total": 5,
"product_available": 3,
"product_bought_by": [
{
"customer": "Kobe",
"date": "2017-07-08"
},
{
"customer": "Maxsu",
"date": "2018-07-28"
}
]
}
在上面這個文件中,已經在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:"Curry",date:"2017-08-08"}}
}
})
嵌入式文件和使用findAndModify
查詢的方法確保產品購買資訊僅在產品可用時才更新。 而整個這個事務在同一個查詢中是原子的。
與此相反的是如果分別保留產品數量,以及誰購買產品的資訊。在這種情況下,我們將首先使用第一個查詢檢查產品是否可用。然後在第二個查詢中更新購買資訊。 但是,有可能在執行這兩個查詢時(還未執行完),其他一些使用者已經購買了該產品,並且此產品缺貨了。但是由於程式執行過程中並不知曉,第二個查詢將根據第一個查詢的結果更新購買資訊。這會導致資料庫不一致,因為產品已經沒有庫存,但是仍然斷續銷售。