|
在這篇文章中,我將使用三個(gè)方法處理樂觀鎖,包括ADO.NET數(shù)據(jù)集、SQL Server時(shí)間戳數(shù)據(jù)類型和新舊值檢查,首先我們從并發(fā)談起,探討5個(gè)并發(fā)問題,然后從實(shí)際出發(fā),利用這三種方法實(shí)現(xiàn)樂觀鎖。
為什么需要鎖?
在多用戶環(huán)境中,大家同時(shí)更新相同的記錄可能會(huì)引發(fā)沖突,這個(gè)問題用專業(yè)的術(shù)語描述就叫做并發(fā)性。并發(fā)會(huì)造成什么樣的沖突?并發(fā)主要會(huì)導(dǎo)致四種常見的問題,詳細(xì)情況請(qǐng)看下表。
如何解決上述沖突?
答案是使用樂觀鎖或悲觀鎖,下面將進(jìn)一步進(jìn)行闡述。什么是樂觀鎖?顧名思義,樂觀鎖假設(shè)多個(gè)事務(wù)相互不會(huì)影響對(duì)方,換句話說就是,在樂觀鎖模式下,沒有鎖操作會(huì)得到執(zhí)行,事務(wù)只是驗(yàn)證是否有其它事務(wù)修改數(shù)據(jù),如果有則進(jìn)行事務(wù)回滾,否則就提交。
樂觀鎖是如何工作的?
1、實(shí)現(xiàn)樂觀鎖的方法有多種,但基本原則都一樣,總是少不了下面五個(gè)步驟:
2、記錄當(dāng)前的時(shí)間戳
3、開始修改值
4、在更新前,檢查是否有其他人更新了值(通過檢查新舊時(shí)間戳實(shí)現(xiàn))
5、如果不相等就回滾,否則就提交
圖 1 樂觀鎖的工作原理
實(shí)現(xiàn)樂觀鎖的解決方案
在.NET中,實(shí)現(xiàn)樂觀鎖的方法主要有三種:
1、數(shù)據(jù)集(Dataset):數(shù)據(jù)集是實(shí)現(xiàn)樂觀鎖的默認(rèn)方法,在更新前它會(huì)檢查新舊值。
2、時(shí)間戳數(shù)據(jù)類型(timestamp):在你的表中創(chuàng)建一個(gè)timestamp數(shù)據(jù)類型,在更新時(shí),檢查舊時(shí)間戳是否等于新時(shí)間戳。
3、直接檢查新舊值:在更新時(shí)檢查舊值和新值是否相等,如果不相等就回滾,否則就提交。
解決方案1:數(shù)據(jù)集
正如前面所說的,數(shù)據(jù)集是處理樂觀鎖的默認(rèn)方法,下面是一個(gè)簡(jiǎn)單的快照,在Adapter的update函數(shù)上有一個(gè)調(diào)試點(diǎn),當(dāng)我移除斷點(diǎn)運(yùn)行update函數(shù)時(shí),它拋出如下圖所示的并行異常錯(cuò)誤。
圖 2 Update函數(shù)執(zhí)行時(shí)拋出的異常錯(cuò)誤
如果你運(yùn)行后端分析器,你將會(huì)看到更新語句檢查當(dāng)前值和舊值是否相等:
在這種情況下,我嘗試將“AuthorName”字段值修改為“This isnew”,但更新時(shí)會(huì)檢查舊值“This is old author”,下面是比較舊值的精簡(jiǎn)代碼段:
解決方案2:使用timestamp數(shù)據(jù)類型
SQL Server有一個(gè)數(shù)據(jù)類型是timestamp,它是實(shí)現(xiàn)樂觀鎖的另一種途徑,每次更新SQL Server數(shù)據(jù)時(shí),時(shí)間戳?xí)詣?dòng)產(chǎn)生一個(gè)唯一的二進(jìn)制數(shù)值,時(shí)間戳數(shù)據(jù)類型可用來版本化你的記錄更新。
圖 3 timestamp數(shù)據(jù)類型
為了實(shí)現(xiàn)樂觀鎖,首先需要取得舊的時(shí)間戳值,在更新時(shí)檢查舊的時(shí)間戳值是否等于當(dāng)前時(shí)間戳,如:
然后檢查是否發(fā)生了更新操作,如果沒有發(fā)生更新,則使用SQL Server的raiserror產(chǎn)生一系列錯(cuò)誤消息。
如果發(fā)生了并發(fā)沖突,當(dāng)你如下圖所示這樣調(diào)用ExecuteNonQuery時(shí),你應(yīng)該會(huì)看到錯(cuò)誤傳播。
圖 4 時(shí)間戳發(fā)生變化,存儲(chǔ)過程產(chǎn)生了錯(cuò)誤
解決方案3:檢查舊值和新值
許多時(shí)候,我們只需要檢查相關(guān)字段值的一致性,其它字段則可以忽略,在update語句中,我們可以直接做這種比較。
NET技術(shù):技術(shù)詳解:三招優(yōu)化.NET中的鎖(組團(tuán)),轉(zhuǎn)載需保留來源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。