名稱解釋
悲觀鎖
定義:我修改數據的時候,不允許別人修改數據。
意圖:並發很容易發生(悲觀者經常認為某件壞事會發生在自己身上)。
場景:績效評分的過程,因為每個評估人評分后都要修改評估結果表的同一行記錄,而且經常是在同一個時間段進行的評分,評分的過程就適合用悲觀鎖。
樂觀鎖
定義:誰都可以修改數據,提交的時候和數據庫做比較,如果數據在這期間發生了變化,有兩種處理思路:1、失敗;2、合並后提交。
意圖:並發不容易發生(樂觀者經常認為某件壞事不會發生在自己身上)。
場景:多個人事管理員都可以修改勞動合同,因為這種並發場景很少發生,因此此處采用樂觀鎖會好很多。
離線
定義:也叫長事務;一次業務過程需要多次的和服務器通信。
意圖:業務要求。
場景:修改審批流程的過程會持續多個請求,多個請求必須作為一個長事務對待。
在線
定義:也叫短事務;一次業務過程只和服務器通信一次。
意圖:業務要求
場景:多數業務屬於這種場景。
在線悲觀鎖
代碼示例
請查看我的這篇博客.NET:臟讀、不可重復讀和幻讀代碼示例,基本上將隔離基本設置為“可重復讀”就可以滿足隔離要求。
在線樂觀鎖
代碼示例
1 [TestMethod] 2 [ExpectedException(typeof(DbUpdateConcurrencyException))] 3 public void 樂觀鎖測試() 4 { 5 using (var context1 = new TestEntities()) 6 { 7 context1.Users.First().Name = "李妞妞1"; 8 9 using (var context2 = new TestEntities()) 10 { 11 context2.Users.First().Name = "李妞妞2"; 12 context2.SaveChanges(); 13 } 14 15 context1.SaveChanges(); 16 } 17 }
此處利用了EntityFramework自帶的樂觀並發機制(版本字段),多數ORM框架都提供這種支持,自己實現也不難,在此就不說了。
離線悲觀鎖
難點是解決離線悲觀鎖的獲取和釋放時機,常見的思路是打開Form時判斷是否被鎖,如果沒有被鎖,就獲取鎖,關閉Form時釋放鎖,會話過期時釋放所有鎖。鎖的管理接口如下:
1 public interface I離線悲觀鎖管理接口 2 { 3 bool 是否被鎖(Guid 單據標識); 4 5 void 獲取鎖(Guid 用戶標識, Guid 單據標識); 6 7 void 釋放鎖(Guid 用戶標識, Guid 單據標識); 8 9 void 釋放鎖(Guid 用戶標識); 10 }
離線樂觀鎖
服務器端代碼和“在線樂觀鎖”一樣,唯一要處理的是在長事務過程中如何在多個請求中存儲和傳輸“版本字段”,常見的方式有url參數和頁面html等,在此就不說了。