MongoDB: 原子性和事務(wù)
原文鏈接: Atomicity and Transactions
在MongoDB中, 文檔級(jí)別的的寫(xiě)操作是原子性的, 甚至是在對(duì)某個(gè)文檔的操作中修改其多個(gè)內(nèi)嵌的子文檔, 也是原子性的.
在一個(gè)寫(xiě)操作同時(shí)修改多個(gè)文檔的情況, 對(duì)其中單獨(dú)的某個(gè)文檔而言是原子的, 但是對(duì)整批文檔而言并不是原子的, 其他的操作很可能會(huì)交錯(cuò)修改數(shù)據(jù). 然而, 可以通過(guò)使用$isolated操作符, 隔離某個(gè)修改多個(gè)文檔的寫(xiě)操作.
$isolated 操作符
通過(guò)使用$isolated操作符, 多文檔寫(xiě)操作一旦開(kāi)始寫(xiě)第一個(gè)文檔,就會(huì)阻止其他進(jìn)程交錯(cuò)修改. 這就確保了沒(méi)有客戶(hù)端可以看到數(shù)據(jù)變化, 直到寫(xiě)操作成功或者報(bào)錯(cuò).
$isolated操作符不支持sharded clusters
然而 isolated 寫(xiě)操作無(wú)法提供 “all-or-nothing” 原子性的保障. 這意味著寫(xiě)操作出錯(cuò)時(shí), 無(wú)法回滾發(fā)生錯(cuò)誤之前的所有的變化.
注意:
$isolated 操作符會(huì)導(dǎo)致寫(xiě)操作請(qǐng)求一個(gè)集合級(jí)別的排它鎖, 即使使用了支持文檔級(jí)別鎖的 WiredTiger 存儲(chǔ)引擎的情況下也一樣. 這意味著, $isolated 操作符會(huì)使得 WiredTiger 在操作期間單線(xiàn)程化.
再次重申一遍, $isolated操作符不支持sharded clusters
使用$isolated操作符的更新操作的例子, 請(qǐng)參見(jiàn): $isolated
使用$isolated操作符刪除操作的例子, 請(qǐng)參見(jiàn): Isolate Remove Operations.
類(lèi)事務(wù)語(yǔ)義
單個(gè)文檔中可以?xún)?nèi)嵌多個(gè)子文檔, 所以單文檔原子性可以滿(mǎn)足多數(shù)實(shí)際使用需求.對(duì)于涉及多文檔的寫(xiě)操作序列必須作為一個(gè)單獨(dú)的事務(wù)對(duì)待的情況, 可以在應(yīng)用中實(shí)現(xiàn)一個(gè)two-phase commits 兩步提交. 然而, two-phase commits只能提供類(lèi)似事務(wù)的語(yǔ)義. 使用two-phase commits可以確保數(shù)據(jù)的一致性(最終結(jié)果的一致性), 但是可能會(huì)使得應(yīng)用程序(不小心)讀到在two-phase commits或rollback期間產(chǎn)生的中間數(shù)據(jù).
關(guān)于two-phase commit 和 rollback的更多信息, 請(qǐng)參見(jiàn): Perform Two Phase Commits
并發(fā)控制
并發(fā)控制允許多個(gè)應(yīng)用并發(fā)執(zhí)行, 不會(huì)導(dǎo)致數(shù)據(jù)的不一致性或沖突. 方法一是在一個(gè)字段上創(chuàng)建一個(gè)唯一索引, 使得該字段只能有一個(gè)唯一的值. 這樣就避免了插入或更新時(shí)帶來(lái)重復(fù)數(shù)據(jù). 對(duì)于多個(gè)字段, 在其上創(chuàng)建唯一索引來(lái)強(qiáng)制這些個(gè)字段值組合的唯一性. 例子請(qǐng)參見(jiàn) update() and Unique Index 和 findAndModify() and Unique Index. 另一個(gè)方法是為寫(xiě)操作在查詢(xún)謂詞中指定字段所期望的當(dāng)前值, 具體例子請(qǐng)參見(jiàn): Update if Current
two-phase commit 模式提供了一個(gè)變種, 在查詢(xún)操作中, 其查詢(xún)謂詞中使用應(yīng)用程序標(biāo)識(shí)代替了某種期待的數(shù)據(jù)狀態(tài)值.