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