概述
幾乎所有的企業應用程序都有多個用戶和后台線程,它們可以同時更新數據庫。兩個數據庫處理事務同時訪問同一份數據的情形很常見,但是這樣很可能導致數據庫的不一致,或者引起應用程序行為異常。
大部分應用程序必須處理多個事務並發訪問同一份數據的情況,而這會影響業務層和表示層的設計。
悲觀鎖
你可以利用事務的隔離級別實現悲觀鎖,一般用“可重復讀”和“串行化”就可以滿足悲觀鎖的要求。
從表面上看,這種方法看似非常簡單,但是這類事務也存在問題,由於隔離事務如何實現完全由平台或數據庫提供,因此有時他們會導致性能降低,令人無法接受 。鑒於此,許多應用程序都避免使用這類事務,轉而采用樂觀鎖。
樂觀鎖
處理並發更新的另一種方式是使用樂觀鎖。樂觀鎖的工作原理是讓應用程序檢查它即將更新的數據是否已經被另一個事務修改過。實現樂觀鎖的一種常見做法是在每個表里添加一個版本字段,每次應用程序更新數據表記錄時就增加這個版本字段。每個UPDATE語句中的WHERE子句會根據上次讀取的值來判斷這個版本號是否發生改變。如果這條記錄已被另外一個事務更新或刪除,應用程序可以回滾這個事務,並重新開始。
基本上所有的數據庫訪問框架都會封裝樂觀鎖功能,比如:EntityFramework和Nhibernate。
樂觀鎖的名稱源自如下假定,即並發更新的幾率極小,此外應用程序並不阻止並發更新,而是檢測並發更新,並從並發更新中恢復過來。
悲觀離線鎖
悲觀離線鎖使用如下方式處理跨越一系列數據庫事務的並發更新:在編輯過程開始之初,就鎖定共享數據,以防止其他用戶編輯共享數據。這種方式與之前描述的悲觀鎖機制類似,只不過這里的鎖是由應用程序而不是數據庫提供。
樂觀離線鎖
樂觀離線鎖使用如下方式處理跨越一系列數據庫事務的並發更新:樂觀離線鎖擴展了此前描述的樂觀鎖機制,在編輯過程的最后一個數據庫事務中,檢查數據庫自最初讀取后沒有被改變。
由於樂觀離線鎖只在用戶要保存修改后的數據時才進行檢測,因此只有當重新開始對用戶來說不是負擔時,這種模式才有效。
常用並發決策
決策 | 選項 |
在線並發策略 | 樂觀鎖 悲觀鎖(必要時) |
離線並發策略 | 樂觀離線鎖模式 悲觀離線鎖模式(必要時) |
博客資源
.NET:在線悲觀鎖、在線樂觀鎖、離線悲觀鎖、離線樂觀鎖代碼示例
圖書資源
《POJO IN ACTION》(該文章就是從這本書上抄襲的)
《企業應用架構模式》