什麼是MongoDB原子操作
MongoDB 並不支援多文件原子事務(multi-document atomic transactions)。但它提供了針對單個文件的原子操作。假如一個文件包含數百個欄位,則 update 語句將更新所有的欄位,或者一個也不更新,從而維持了文件級的原子性。
原子操作資料模型
維持原子性的建議方法是利用內嵌文件(embedded document)將所有經常更新的相關資訊都儲存在一個文件中。這能確保所有針對單一文件的更新具有原子性。
考慮下列關於產品的文件:
{
"_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 查詢的方法確保了,只有當產品還有足夠數量時,才更新產品購買資訊。在整個過程中,同一查詢中的事務是原子性的。
與之相反的情況是,我們可能會想分別保持產品可用性與購買產品的顧客資訊。在這種情況下,我們會首先使用第一個查詢來檢查產品是否夠用。然後在第二個查詢中更新購買資訊。但在這兩個查詢的執行過程之間,其他一些顧客也可能會購買了產品,從而使產品變得不夠用了。由於沒有了解到這種情況,我們的第二個查詢根據第一個查詢的結果進行了更新。這將造成資料庫的不一致性。