鍍金池/ 教程/ 數(shù)據(jù)庫(kù)/ 原子操作
更新文檔
GridFS
Rockmongo 管理工具
Map Reduce
Java
創(chuàng)建備份
數(shù)據(jù)模型
創(chuàng)建數(shù)據(jù)庫(kù)
映射
查詢文檔
索引限制
ObjectId
刪除文檔
數(shù)據(jù)類型
高級(jí)索引
索引
優(yōu)勢(shì)
記錄排序
查詢分析
插入文檔
刪除集合
全文檢索
創(chuàng)建集合
概述
數(shù)據(jù)庫(kù)引用
覆蓋索引查詢
安裝環(huán)境
PHP
刪除數(shù)據(jù)庫(kù)
固定集合
關(guān)系
聚合
自動(dòng)增長(zhǎng)
復(fù)制
限制記錄
部署
分片
正則表達(dá)式
原子操作

原子操作

MongoDB 并不支持多文檔原子事務(wù)(multi-document atomic transactions)。但它提供了針對(duì)單個(gè)文檔的原子操作。假如一個(gè)文檔包含數(shù)百個(gè)字段,則 update 語(yǔ)句將更新所有的字段,或者一個(gè)也不更新,從而維持了文檔級(jí)的原子性。

原子操作數(shù)據(jù)模型

維持原子性的建議方法是利用內(nèi)嵌文檔(embedded document)將所有經(jīng)常更新的相關(guān)信息都保存在一個(gè)文檔中。這能確保所有針對(duì)單一文檔的更新具有原子性。

考慮下列關(guān)于產(chǎn)品的文檔:

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

在這個(gè)文檔中,將購(gòu)買(mǎi)產(chǎn)品的顧客的信息內(nèi)嵌在 product_bought_by 字段中。無(wú)論何時(shí),只要新顧客購(gòu)買(mǎi)產(chǎn)品,我們就能使用 product_available 字段查看產(chǎn)品是否還有足夠的數(shù)量。如果產(chǎn)品還有,就減少 product_available 字段值,并且將新顧客的內(nèi)嵌文檔插入到 product_bought_by 字段中。使用 findAndModify 命令來(lái)實(shí)現(xiàn)該功能,因?yàn)樗芡瑫r(shí)搜索并更新文檔。

>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"}} 
   }    
})

上述內(nèi)嵌文檔并使用 findAndModify 查詢的方法確保了,只有當(dāng)產(chǎn)品還有足夠數(shù)量時(shí),才更新產(chǎn)品購(gòu)買(mǎi)信息。在整個(gè)過(guò)程中,同一查詢中的事務(wù)是原子性的。

與之相反的情況是,我們可能會(huì)想分別保持產(chǎn)品可用性與購(gòu)買(mǎi)產(chǎn)品的顧客信息。在這種情況下,我們會(huì)首先使用第一個(gè)查詢來(lái)檢查產(chǎn)品是否夠用。然后在第二個(gè)查詢中更新購(gòu)買(mǎi)信息。但在這兩個(gè)查詢的執(zhí)行過(guò)程之間,其他一些顧客也可能會(huì)購(gòu)買(mǎi)了產(chǎn)品,從而使產(chǎn)品變得不夠用了。由于沒(méi)有了解到這種情況,我們的第二個(gè)查詢根據(jù)第一個(gè)查詢的結(jié)果進(jìn)行了更新。這將造成數(shù)據(jù)庫(kù)的不一致性。

上一篇:記錄排序下一篇:聚合