搜尋

首頁  >  問答  >  主體

node.js - mongo的事务一致性如何保持

我现在有2个操作,一个insert,一个update,都是对一张表操作的,如何保证事务一致性? upinsert可以多条数据么? mongo官方文档上有Perform Two Phase Commits的文章。除了这个还有其他方案么?

怪我咯怪我咯2782 天前593

全部回覆(1)我來回復

  • PHP中文网

    PHP中文网2017-04-17 11:36:47

    Upsert的意思是沒有資料的時候加入一條,那麼「多條資料」指的是什麼呢?

    If set to true, creates a new document when no document matches the query criteria.

    回到一致性和這個文章上,中國社區非常給力,官方文檔也有中文翻譯了!這篇文章是為了模擬出傳統資料庫中 ACID 裡多個操作的 Atomic 和 Consistency。 Atomic 指要嘛操作全都執行,要嘛都不執行,不能執行一半,改了幾條數據了,看哎喲好像不對,那扔著吧。 Consistency 在資料庫領域的意思跟在分散式系統裡的意思不一樣,指資料的外部約束有沒有滿足,例如帳戶之間轉賬,不能最後總和還是負數,或者超過原來的總和了。

    那文檔中的辦法是怎麼做的呢?簡單說,就是在執行操作之前,先記下來要做什麼,以後可以 redo。然後要確保每個操作都是 冪等的 ,就是說重複執行也沒事。例如,賦值是冪等的,但加一個數就不是冪等的。利用 MongoDB 提供的單一文檔的原子性,使用一些輔助的資料做到冪等,最後把輔助的資料清除掉。如果你的操作本身就是冪等的,那就不需要輔助資料了。如果要 undo,也是可能的,那就要記下如何 undo。

    但是 ACID 中的 Isolation 是沒有的,也就是說事務之間有交叉,別的並發操作可以看到中間不一致的狀態,上面說的外部約束只能最終得到保證。比如說,事務 T1 包括 (张三:加100;李四:减100),事務 T2 包括 (张三:加200;李四:减200),如果不加以限制,可能的順序是:

    1. T1 (張三:加100)
    2. T2 (張三:加200)
    3. T2 (李四:減200)
    4. T1 (李四:減100)

    T2 執行的時候可以讀取並修改 T1 的中間結果,在轉帳這個問題上沒有大問題,因為加減是 可交換 的操作,先後不影響最終結果。但是如果我們把事務改成 T1 (张三 = 100;李四 = 100)T2 (张三 = 200;李四 = 200) 這樣最終的結果就可能是 (张三 = 200;李四 = 100),有可能就不滿足一致性了。但是如果能在應用程式裡保證順序地執行這兩個事務,問題就避免了。

    大家也了解 Isolation 有幾個級別,還有多版本等更複雜的。傳統資料庫在單機上也會在更強的 Isolation 和效能之間做權衡,提供不同的等級可選。這點在分散式系統中被稱為 Consistency,實現的代價就更高了,所以 MongoDB 不支援。不過對大多應用,這並不是太大的問題:

    1. 可能異常狀況在邏輯上也是可以接受的,例如微信群發,每個人收到的順序並不一樣。
    2. 可能邏輯上並發就是不可能的,例如一個使用者只能修改自己的數據,例如只有一個執行緒寫資料。
    3. 或把需要的資料放到一個文檔裡,對單文檔,MongoDB 保證原子性,別的操作也不可能看到文檔一半被改了。
    4. 或可以在應用上層發現並解決。例如支付寶轉帳就自己實現了一套一致性協議,1分鐘內可以保證這筆數據一致了。

    對你的要求,如果可以透過修改資料模型,讓改動在一個文件裡就方便了。最好是看看你具體的需要和應用的假設,分析分析可能出現的異常情況,最後想辦法。還有一個辦法,貴司可以購買MongoDB 的支援服務,針對你現在的產品階段和需求(開發,維護,諮詢,培訓),提供不同類型的專業級支持,比再請個程式設計師/ DevOp / DBA便宜靠譜多了。我會告訴你他們其實也有中文支持麼?

    回覆
    0
  • 取消回覆