在以前的一片隨筆中,簡單的說了一下SQL Server中的隔離級別。而SQL Server的隔離級別是經過鎖的機制來實現的。如今深刻一下,談談SQL Server中的鎖。html
開始以前,先要定義一下前提:sql
1.隔離級別的實現其實就是在不一樣的資源上加鎖。
2.對數據庫的每一次訪問(CRUD)咱們稱其爲一個事務(在begin tran,commit tran|rollback tran中的語句塊,或者即席查詢--單條SQL)。不一樣的事務若是同時訪問同一個數據庫資源,會產生一系列的問題(見 Sql Server隔離級別(1) )。
3.大多數的事務在訪問資源以前都會嘗試對資源加上對應的鎖(acquire lock,請求一個鎖)。只有在Read Uncommitted隔離級別以及在表上加了WITH(No Lock) hint的Select語句不會請求鎖。
3.讀鎖(共享鎖S)不會阻塞讀鎖,讀鎖會阻塞寫鎖(獨佔鎖X),寫鎖會阻塞讀鎖。
4.在一個事務中,只有在Repeatable Read或更高的隔離級別下,會將select語句的讀鎖一直保持到事務結束(提交或回滾),Read Committed隔離級別會形成不可重複讀的緣由就是在事務中的select語句執行完成後(事務沒有執行完)讀鎖就直接釋放了。數據庫
5.當前事務中的鎖能夠經過SELECT * FROM sys.dm_tran_locks 這個查詢查看併發
====================================開始的分割線=========================================================post
Server中存在不一樣粒度的鎖:行鎖,鍵鎖,頁鎖,表鎖等等,之因此要存在這些鎖,是爲了在併發性與系統開銷間作一個平衡。粒度更小的鎖將帶了更好的併發性和更大的系統開銷例如行鎖的併發性好於表鎖,不過系統的開銷卻大於表鎖。性能
a.獲取表鎖時:整張表包括未被查詢使用的行將會被鎖住,其餘試圖請求表上不兼容鎖的查詢都將等待。此時系統中只須要維護一個表鎖便可。ui
b.獲取行鎖時:只有查詢使用到的行會被鎖住,請求其餘行的查詢能夠順利的進行。此時併發性好於a,可是對於每個被使用的行系統都要維護一個鎖,系統開銷增長。url
一下是一些鎖的資源,這裏先大概瞭解下就好htm
資源blog |
說明 |
---|---|
RID |
行標識,用於鎖住整個表的其中一行 |
KEY |
經過在索引來鎖住行,用於在序列化的隔離級別中鎖住一個行的範圍。 |
PAGE |
8kb大小的數據頁或者索引頁 |
EXTENT |
一組連續的八頁,例如數據頁或索引頁。 |
TABLE |
包括全部數據和索引的整個表。 |
DATABASE |
數據庫。 |
在一個SQL執行的時候,或多或少都會請求上述的資源,而對這些資源的請求能夠當作是對這些資源上的鎖的請求。只有成功的請求到這些資源上的鎖或者說成功的在當前的事務中對這些資源加鎖,才能對這些資源進行CRUD的操做。
對於不一樣的資源請求,SQL Server會應用不一樣的鎖模式來試圖在資源上加鎖。常常接觸到的鎖模式以下:
共享鎖(S):
請求到共享鎖(讀鎖)容許事務能夠讀取某一個資源,此時其餘的事務將請求不到該資源的獨佔鎖(寫鎖),可是能夠請求到共享鎖。在資源讀取完成後,共享鎖將會釋放(即便此時事務尚未結束)。除非事務在read repeatable或者更高的隔離級別下執行,或者經過使用sql hint在事務執行時一直持有鎖(例如WITH(HOLDLOCK)),共享鎖將持續到事務結束。
更新鎖(U):
更新鎖的存在是爲了不在併發環境下不一樣事務的Update語句形成死鎖。
一個典型的Update操做將通過如下兩步:
步驟1.獲取將要更新的資源的共享鎖將數據讀出
步驟2.將共享鎖轉換成獨佔鎖並將更新的數據寫入到資源中
考慮到併發環境,兩個事務同時到達步驟1,獲取到同一資源的共享鎖(共享鎖之間不會阻塞)。而後兩個事務都開始將試圖共享鎖轉換成獨佔鎖,發現沒法轉換,由於此時兩個事務同時還保留了對資源的共享鎖,而共享鎖是會阻塞獨佔鎖的。兩個事務都等待對方的共享鎖釋放,因而就產生了死鎖。
上述的Update模式中,一個Update操做將再也不是原子操做,由於在步驟1到步驟2之間會被其餘的事務影響。因此須要引入更新鎖來替換步驟1中獲取的共享鎖,更新鎖是互斥的,因此將不會出現兩個Update操做同時獲取到更新鎖的狀況。只多是一個事務獲取到了更新鎖,而另外一個事務只好等待更新鎖的釋放。
在Update用更新鎖來替代共享鎖來查找資源將防止併發更新產生死鎖,而且因爲更新鎖能夠和共享鎖兼容,因此其餘的事務依然能夠在資源上放置共享鎖。
獨佔鎖(X)
獨佔鎖阻塞其餘的全部鎖,沒法讀取或者修改加了獨佔鎖的資源。
意向鎖(IS,IX,SIX)一個意向鎖代表Sql Server但願獲取當前資源的層次更低的共享鎖或者獨佔鎖。例如,表上的IS鎖(意向共享鎖)代表事務將要表中的頁或者行(粒度比表更小的資源)上放置共享鎖,而放置意向鎖將避免隨後的其餘事務在表上獲取到獨佔鎖。意向鎖可以提升性能,由於當一個事務要獲取一個表的鎖的時候不用再去檢查表的資資源(頁或行)是否被鎖住了, 而只須要檢查表上是否有意向鎖就好了。