在MongoDB中實現樂觀併發控制

2021-09-03 10:18:57 字數 1783 閱讀 9300

說起來,自從接觸了mongodb以後,我在大小專案中就再也沒有接觸過關係型資料庫了。效能倒不是什麼主要問題,主要是方便,例如我可以在mongodb中直接儲存陣列,然後把其中的元素當作查詢條件,而在關係型資料庫中,則需要使用額外的**,然後再join等等。當然,在mongodb中很難進行join,於是對於某些場景下會略顯麻煩,但在記憶中我似乎真沒什麼束手束腳的情況。這方面我還沒有仔細分析,可能mongodb支援儲存複雜物件會有所幫助吧。以上都是廢話,這裡我簡單談一下如何在mongodb中實現樂觀併發控制。當然加入您對mongodb的功能都有所了解,那麼這種做法也是十分顯而易見的。

簡單地說,「併發控制」便是避免在併發環境下某條記錄被錯誤地覆蓋。例如在一次「讀取」、「修改」、「提交」的事務中,除非進行合理控制,否則可能其中某次提交的資料就遺失了。所謂「悲觀」併發控制,則意味著在某次事務的「開始」和「提交」之間不會出現任何「讀取」操作(即這條記錄被鎖定了),這自然不會有問題。而樂觀併發控制,則保證的是在某次「讀取」和「提交」之間沒有進行任何「提交」操作,否則便會提交失敗,於是當前事務便會重新從「讀取」這個最早的步驟開始。此類概念(或者說併發處理方式)在許多地方都有體現,例如在普通的併發程式設計中,lock就近似於「悲觀」併發控制,而「軟體事務記憶體」則類似於「樂觀」併發控制。

如果要在普通的關係型資料庫裡實現樂觀併發控制,我們一般需要為其加上乙個額外的version欄位,它是整型,也可能是個時間戳。在更新某條記錄時,我們將這個欄位的「舊值」作為update語句的條件之一,同時這個欄位也會寫入新的值。如果這次更新影響了某條記錄,那麼表示更新成功,反之則表示這條記錄已經被刪除,或是在「讀取」和「提交」之間遇到了其他提交操作。在sql server中存在乙個timestamp型別,這個型別的字段會在記錄修改時自動更新。

在mongodb中的做法也沒有太大區別,只是它的update語句並不會返回它所影響的記錄數,於是我們必須額外進行一次查詢,例如文件上所記載:

> t.update(}, });

> db.$cmd.findone();

// it worked

> t.update(}, });

> db.$cmd.findone();

// did not work

我們可以在update語句後面跟上一句db.$cmd查詢,如果它返回updatedexisting為true,則表示更新成功了。我一開始擔心db.$cmd查詢的結果是否準確:如果在update語句和db.$cmd查詢之間,另外乙個連線恰好也執行了一次update操作,那麼db.$cmd返回的是哪次更新的結果?從後來從郵件列表中得知,db.$cmd查詢是與連線相關,這便不會有問題了。不過值得注意的是,如果您使用的的驅動程式是「自動管理連線」的,則可能您在程式中發起的兩次查詢會使用兩個不同的鏈結。不過我猜成熟的驅動應該都有辦法解決這個問題,例如mongodb的官方.net驅動便可以要求直接返回db.$cmd查詢的結果,或者在**裡顯式「固定」某個鏈結。如今mongodb的官方驅動已經十分完善,將mongodb的功能體現地淋漓盡致,我也正在它的基礎上更新easymongo(經過幾個專案使用,感想不錯),和之前的「民間驅動」相比省了不少心——順便一提,官方驅動其實也借用了民間驅動的不少**,即便它們之間的api有許多差異。

除此之外,您也可以使用基於runcommand的findandmodify命令進行更新,更新條件自然同樣需要包括版本號。如果更新成功,那麼findandmodify命令則會返回「更新前」的資料,否則則返回空文件。一般來說,mongodb的驅動也已經包含了runcommand命令,甚至對findandmodify的直接支援(例如官方的.net驅動)。

正如我一開始所說的那樣,其實如果您了解mongodb的功能,本文內容其實是十分顯而易見的,的確就是這麼簡單。

在MVC中實現MongoDB的分頁查詢

使用的mongodb net 驅動是 mongodb.driver.2.4.4 首先確定的是mongodb的bsondocument結構 var document new bsondocument 其中,operation 中的bsondocument中的key,value鍵值對是可變長的,也就是說...

mysql實現樂觀鎖解決併發問題

樂觀鎖 optimistic locking 相對悲觀鎖而言,樂觀鎖假設認為資料一般情況下不會造成衝突,所以在資料進行提交更新的時候,才會正式對資料的衝突與否進行檢測,如果發現衝突了,則讓返回使用者錯誤的資訊,讓使用者決定如何去做。那麼我們如何實現樂觀鎖呢,一般來說有以下2種方式 1 使用版本號實現...

mybatis plus中實現樂觀鎖

1.主要適用場景 當要更新一條記錄的時候,希望這條記錄沒有被別人更新,也就是說實現執行緒安全的資料更新 2.樂觀鎖實現方式 在資料庫新增version欄位,預設為1 取出記錄時,獲取當前version 假設取出的version 1 select id,name,age,email,create ti...