SQL Server數(shù)據(jù)庫(kù)高級(jí)進(jìn)階之鎖實(shí)戰(zhàn)演練

一、SQL Server鎖的本質(zhì)

鎖的定義:鎖主要用于多用戶環(huán)境下,保證數(shù)據(jù)庫(kù)完整性和一致性的技術(shù)。

鎖的解釋:當(dāng)多個(gè)用戶并發(fā)地存取數(shù)據(jù)時(shí),在數(shù)據(jù)庫(kù)中就會(huì)產(chǎn)生多個(gè)事務(wù)同時(shí)存取同一數(shù)據(jù)的情況。若對(duì)并發(fā)操作不加控制就可能會(huì)讀取和存儲(chǔ)不正確的數(shù)據(jù),破壞數(shù)據(jù)庫(kù)的完整性和一致性。當(dāng)事務(wù)在對(duì)某個(gè)數(shù)據(jù)對(duì)象進(jìn)行操作前,先向系統(tǒng)發(fā)出請(qǐng)求,對(duì)其加鎖。加鎖后事務(wù)就對(duì)該數(shù)據(jù)對(duì)象有了一定的控制。

二、SQL Server鎖的分類

鎖的分類,在教材上,網(wǎng)絡(luò)上好多都是按兩個(gè)維度來(lái)描述的。一種維度是按鎖的功能來(lái)劃分,一種維度是按概念來(lái)劃分。

1)、按概念劃分(從程序員的角度看)

???悲觀鎖(Pessimistic Lock)

???樂(lè)觀鎖(Optimistic Lock)

2)、按鎖的功能來(lái)劃分(從數(shù)據(jù)庫(kù)系統(tǒng)的角度來(lái)看)

???共享鎖 (S) ?(Shared (S) Locks) 用于不更改或不更新數(shù)據(jù)的操作(只讀操作),如SELECT語(yǔ)句。

???更新鎖 (U) (Update (U) Locks)用于可更新的資源中。防止當(dāng)多個(gè)會(huì)話在讀取、鎖定以及隨后可能進(jìn)行的資源更新時(shí)發(fā)生常見形式的死鎖。

???排它鎖 (X) (Exclusive (X) Locks)?用于數(shù)據(jù)修改操作,例如INSERT、UPDATE或DELETE。確保不會(huì)同時(shí)對(duì)同一資源進(jìn)行多重更新。

???意向鎖 (I)(Intent Locks)?用于建立鎖的層次結(jié)構(gòu)。意向鎖的類型為:意向共享(IS)、意向排它(IX)以及與意向排它共享(SIX)。

SQL Server數(shù)據(jù)庫(kù)高級(jí)進(jìn)階之鎖實(shí)戰(zhàn)演練

三、認(rèn)識(shí)SQL Server數(shù)據(jù)庫(kù)鎖

1)、共享鎖 (S)

?共享鎖 (S) (Shared (S) Locks)?用于不更改或不更新數(shù)據(jù)的操作(只讀操作),如SELECT語(yǔ)句。

2)、?更新鎖 (U)

?更新鎖 (U) (Update (U) Locks)?用于可更新的資源中。防止當(dāng)多個(gè)會(huì)話在讀取、鎖定以及隨后可能進(jìn)行的資源更新時(shí)發(fā)生常見形式的死鎖。

3)、排它鎖 (X)

排它鎖 (X) (Exclusive (X) Locks)?用于數(shù)據(jù)修改操作,例如INSERT、UPDATE或DELETE。確保不會(huì)同時(shí)對(duì)同一資源進(jìn)行多重更新。

4)、意向鎖 (I)

意向鎖 (I)?(Intent Locks)??用于建立鎖的層次結(jié)構(gòu)。意向鎖的類型為:意向共享(IS)、意向排它(IX)以及與意向排它共享(SIX)。

四、如何避免鎖升級(jí)

?? 1、防止鎖升級(jí)的最簡(jiǎn)單,最安全的方法是保持事務(wù)的簡(jiǎn)短,并減少昂貴查詢的鎖占用空間,以便不超過(guò)鎖升級(jí)閾值,有幾種方法可以實(shí)現(xiàn)這一目標(biāo)。將大批量操作分解為幾個(gè)較小的操作。刪除大量數(shù)據(jù)的時(shí)候,可以一次只刪除500個(gè),執(zhí)行多次,可以顯著減少每個(gè)事務(wù)累積的鎖定數(shù)量并防止鎖定升級(jí)。

? 2、?創(chuàng)建索引使查詢盡可能高效來(lái)減少查詢的鎖定占用空間。如果沒(méi)有索引會(huì)造成表掃描可能會(huì)增加鎖定升級(jí)的可能性, 更可怕的是,它增加了死鎖的可能性,并且通常會(huì)對(duì)并發(fā)性和性能產(chǎn)生負(fù)面影響。根據(jù)查詢條件創(chuàng)建合適的索引,最大化提升索引查找的效率,此優(yōu)化的一個(gè)目標(biāo)是使索引查找返回盡可能少的行,以最小化查詢的的成本。

五、死鎖的本質(zhì)

死鎖(Dead Lock)

死鎖是指一種進(jìn)程之間互相永久阻塞的狀態(tài),可能涉及兩個(gè)或更多的進(jìn)程。死鎖是指在一組進(jìn)程中的各個(gè)進(jìn)程均占有不會(huì)釋放的資源,但因互相申請(qǐng)被其他進(jìn)程所站用不會(huì)釋放的資源而處于的一種永久等待狀態(tài)。

六、如何預(yù)防死鎖

?首先要理解,在多并發(fā)的環(huán)境中死鎖是不可避免的,只能通過(guò)合理的數(shù)據(jù)庫(kù)設(shè)計(jì)、良好的索引、適當(dāng)?shù)牟樵冋Z(yǔ)句以及隔離等級(jí)等措施盡量減少死鎖。

?最開始列出了死鎖的4個(gè)必要條件,只要想辦法破壞任意1個(gè)或多個(gè)條件就可以避免產(chǎn)生死鎖。下列方法有助于最大限度的降低死鎖:

?a) 按同一順序訪問(wèn)對(duì)象;

?b)避免事務(wù)中的用戶交互,也就是在事務(wù)執(zhí)行過(guò)程中不要包含用戶交互的步驟;

?c)保持事務(wù)簡(jiǎn)短并在一個(gè)批處理中;

?d)SELECT語(yǔ)句加WITH(NOLOCK)提示;

SELECT * FROM TableName WITH(NOLOCK);

七、如何利用鎖來(lái)解決并發(fā)性帶來(lái)的問(wèn)題

1、并發(fā)性具體帶來(lái)什么問(wèn)題?

在多用戶環(huán)境中,在同一時(shí)間可能會(huì)有多個(gè)用戶更新相同的記錄,這會(huì)產(chǎn)生沖突。這就是著名的并發(fā)性問(wèn)題。

1)、臟讀取:當(dāng)一個(gè)事物讀取其它完成一半事務(wù)的記錄時(shí),就會(huì)發(fā)生臟讀取。

例:用戶A和用戶B看到的值都是5,用戶B將值修改為2,用戶A看到的值仍然是5,這時(shí)就發(fā)生了臟讀取。

2)、不可重復(fù)讀取:在每次讀數(shù)據(jù)時(shí),如果你獲得的值都不一樣,那表明你遇到了不可重復(fù)讀取問(wèn)題。

例:用戶A看到的值是5,用戶B將值修改為2,用戶A刷新后看到的值仍然是5,這時(shí)就發(fā)生了不可重復(fù)讀取。

3)、虛幻行:如果update和delect SQL語(yǔ)句未對(duì)數(shù)據(jù)造成影響,很可能遇到了虛幻行問(wèn)題。

例:用戶A將所有值都把5修改為2,用戶B使用值2插入一個(gè)新記錄,用戶A查詢所有值為2的記錄,但卻找不到新添加的記錄,這時(shí)就叫虛幻行。

4)、更新丟失:一個(gè)事務(wù)的更新覆蓋了其它事務(wù)的更新結(jié)果,就是所謂的更新丟失。

例:用戶A將所有值從5修改為2,用戶B將所有值從2修改為5,用戶A丟失了他的更新。

2、如何解決并發(fā)性的問(wèn)題

為了解決這些并發(fā)帶來(lái)的問(wèn)題。 我們需要引入并發(fā)控制機(jī)制。

悲觀鎖(Pessimistic Lock)——應(yīng)用場(chǎng)景:寫多

顧名思義,很悲觀。每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改數(shù)據(jù),所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)阻塞直到它拿到鎖。

樂(lè)觀鎖(Optimistic Lock)——應(yīng)用場(chǎng)景:讀多

顧名思義,很樂(lè)觀,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人不會(huì)修改,所以不會(huì)上鎖,但是在更新的時(shí)候會(huì)判斷在此期間別人有沒(méi)有去更新這個(gè)數(shù)據(jù)。

1,樂(lè)觀鎖適用于多讀的應(yīng)用類型,這樣可以提高吞吐量。

2,樂(lè)觀鎖一般加時(shí)間戳字段(或者自定義版本號(hào)字段)來(lái)實(shí)現(xiàn)。

在實(shí)際生產(chǎn)環(huán)境里邊,如果并發(fā)量不大且不允許臟讀,可以使用悲觀鎖解決并發(fā)問(wèn)題;但如果系統(tǒng)的并發(fā)非常大的話,悲觀鎖定會(huì)帶來(lái)非常大的性能問(wèn)題,所以我們就要選擇樂(lè)觀鎖定的方法。

八、思考與總結(jié)

樂(lè)觀鎖復(fù)雜事務(wù)控制

樂(lè)觀鎖:大多數(shù)是基于數(shù)據(jù)版本(version)的記錄機(jī)制實(shí)現(xiàn)的。即為數(shù)據(jù)增加一個(gè) 版本標(biāo)識(shí),在基于數(shù)據(jù)庫(kù)表的版本解決方案中,一般是通過(guò)為數(shù)據(jù)庫(kù)表添加一個(gè)”version" 字段來(lái)實(shí)現(xiàn)讀取出數(shù)據(jù)時(shí),將此版本號(hào)同讀出,之后更新時(shí),對(duì)此版本號(hào)加1。此時(shí),將提交數(shù)據(jù)的版本號(hào)與數(shù)據(jù)庫(kù)表對(duì)應(yīng)記錄的當(dāng)前版本號(hào)進(jìn)行比對(duì),如果提交的數(shù)據(jù)版本號(hào)大于數(shù)據(jù)庫(kù)當(dāng)前版本號(hào),則予以更新,否則認(rèn)為是過(guò)期數(shù)據(jù)。



騰訊課堂


網(wǎng)易云課堂
不信的話,掃一掃
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容