SQL Server裡的閂鎖介紹

2021-09-22 07:06:44 字數 4136 閱讀 7253

閂鎖首次在sql server 7.0裡引入,同時微軟首次引入了行級別鎖(row-level locking)。對於行級別鎖引入閂鎖的概念是非常重要的,不然的話在記憶體中會出現丟失更新(lost updates)的現象。如我所說的,閂鎖是儲存引擎使用的輕量級同步物件,是sql server用來保護記憶體結構的。閂鎖只不過是類似於多執行緒程式設計裡的所謂的臨界區(critcal section)概念。

在傳統併發程式設計裡,臨界區是同時只能乙個執行緒執行的**。閂鎖本身是個臨界區的特殊版本,因為它允許多個併發讀操作。在sql server的上下文裡這意味著多個執行緒可以併發讀取乙個共享資料結構,例如記憶體中的頁,但是寫入共享資料結構必須是單個執行緒進行。

閂鎖是用來協調資料庫裡多個執行緒物理執行,然而鎖是基於選擇的事務隔離級別,用來邏輯獲得需要的隔離級別。作為開發者或dba的你,你可以用不同方式影響鎖——例如通過sql server裡的隔離級別,或者通過各種可用鎖提示。另一方面閂鎖是不能以直接方式控制的。在sql server裡沒有閂鎖提示,也沒有可用閂鎖隔離級別。下表是鎖和閂鎖之間的比較:

鎖(locks)閂鎖(latches)

更新(update),         共享的(shared),

排它的(exclusive),     更新(update),排它的(exclusive),

意向的(intension)      銷毀(destroy)

從表裡可以看到,閂鎖支援更細粒度保持(keep)和銷毀(destroy)模式。保持閂鎖主要用來引用計數,例如當你想知道在指定閂鎖上有多少其它閂鎖在等待。銷毀閂鎖是最有限制的乙個(它甚至會阻塞保持閂鎖),當閂鎖被銷毀時會用到,例如當惰性寫入器(lazy writer)想要釋放記憶體中的頁時。我們先介紹下各種閂鎖模式,然後說下各個閂鎖模式的相容性。

nl(空閂鎖):

kp(保持閂鎖):

sh(共享閂鎖):

up(更新閂鎖):

ex(排它閂鎖):

dt(銷毀閂鎖):

在sql server裡,一致性不能只用鎖來獲得。sql server還是可以訪問沒被鎖管理器保護的共享資料結構,例如頁頭。還有sql server基於閂鎖基礎的其他元件也是,有單執行緒**路徑。好了,我們繼續講解sql server裡的各種閂鎖型別,還有如何對它們進行故障排除。

sql server區分3個不同閂鎖類別

我們來詳細看下這3個不同類別。當在緩衝池的頁讀寫操作未完成——即當你讀自/寫入你的儲存子系統時(2者未同步),sql server會使用io閂鎖(i/o latches)。對於這些i/o閂鎖,sql server在統計資訊裡以pageiolatch_為字首出現。你可以在dmvsys.dm_os_wait_stats檢視下這些閂鎖型別的等待。

使用這些閂鎖,sql server保證那些頁不會併發多次讀入快取池,那些頁也不會從快取池忽略,在那些頁需要被查詢訪問的時候。

除這些i/o閂鎖外,sql server也支援所謂的快取區閂鎖(buffer latches),它用來保護緩衝池裡頁不會被併發執行的執行緒影響。這些閂鎖,sql server使用它們來阻止記憶體中的丟失更新(lost updates)。沒有這類閂鎖,在快取池裡會有併發的讀寫頁,它們會引發主記憶體裡頁的損壞。對於這些快取閂鎖,sql server在統計資訊裡以pagelatch_為字首出現。你可以在dmvsys.dm_os_wait_stats檢視下這些閂鎖型別的等待。這裡最重要的是你涉及了主記憶體的競爭,因為他們的等待型別名稱裡不包含io字樣。

最後sql server內部使用所謂的非快取區閂鎖(non-buffer latches)來保護除緩衝池外的共享資料結構。對於這些非快取閂鎖,sql server在統計資訊裡以latch_為字首出現。你可以在dmvsys.dm_os_wait_stats檢視下這些閂鎖型別的等待。

但在這個dmv裡這些對於非快取區閂鎖的等待只是sql server內部使用的各個閂鎖的概況資訊,你可以在單獨的dmvsys.dm_os_latch_stats找到更詳細的資訊。

sql server 2014內部使用163個閂鎖來同步共享資料結構的訪問。其中乙個著名的閂鎖是fgcb_add_remove,它用來保護檔案組的檔案組控制阻塞( file group control block (fgcb)),在以下特定操作期間:

當你看到這個閂鎖排在前列是,你肯定有太多自動增長操作的問題,原因是你資料庫糟糕的預設配置。當查詢嘗試讀/寫保護的資料結構且需要等待乙個閂鎖時,查詢就會進入掛起狀態,直到閂鎖可以成功獲取。因此查詢經過的整個查詢生命週期包括執行(running)掛起(suspended)可執行(runnable),最後再次執行(running)。因此,當查詢長時間把持閂鎖時,強制共享資料結構保護才有意義。那是因為改變查詢狀態也意味著進行windows系統裡的上下文切換,依據引入的cpu週期是個很昂貴的操作。

因此對於讀寫頻繁或極短時間內的共享資料結構上放上閂鎖沒有意義。在這個情況下,需要的上下文切換會殺死sql server的整體效能,它需要花費太多的時間來完成整個查詢生命週期(執行(running)掛起(suspended)可執行(runnable))。那就是是sql server引入的所謂自旋鎖(spinlocks)。鎖管理器就是這樣資料結構的好例子:當鎖定或解鎖資料物件(例如記錄,頁等)時只需要單個執行緒訪問。但當你檢視sys.dm_os_latch_stats時,你會發現沒有閂鎖保護鎖管理器本身。鎖管理器使用的雜湊表裡對應的雜湊桶使用自旋鎖來保護——lock_hash自旋鎖通過鎖管理器執行鎖定和解鎖操作前,必須獲得自旋鎖。但今天我不想再講解自旋鎖了,因為我會在專門的文章裡詳細介紹——耐心期待下吧:)

在這個文章裡,我們**了sql server裡的閂鎖。如你所見,閂鎖是sql server使用的輕量級同步物件,用來儲存記憶體裡的共享資料結構。sql server區分3個不同閂鎖型別——io閂鎖,快取區閂鎖和非快取區閂鎖。你也看到了如何使用dmvsys.dm_os_wait_statssys.dm_os_latch_stats進行閂鎖等待的故障排除

簡單介紹SQL Server裡的閂鎖

在今天的文章裡我想談下sql server使用的更高階的,輕量級的同步物件 閂鎖 latch 閂鎖是sql server儲存引擎使用輕量級同步物件,用來保護多執行緒訪問記憶體內結構。文章的第1部分我會介紹sql server裡為什麼需要閂鎖,在第2部分我會給你介紹各個閂鎖型別,還有你如何能對它們進行...

超閂鎖和子閂鎖如何工作的

原文 hot it works sql server superlatch ing sub latches 閂鎖是應用在使用者模式下,在讀寫鎖結構應用在sql server 中用來保護內部結構。trace latch 是sql server 使用閂的例子,被trace controller 類建立並...

SQL server鎖的機制

sql server 的所有活動都會產生鎖。鎖定的單元越小,就越能越能提高併發處理能力,但是管理鎖的開銷越大。如何找到平衡點,使併發性和效能都可接受是 sql server 的難點。sql server 有如下幾種瑣 1 共享鎖用於唯讀操作 select 鎖定共享的資源。共享鎖不會阻止其他使用者讀,...