在談談SQL Server的鎖機制之前來思考以下這個場景當你在酷暑的時候騎著自己的小車往目的地行走時路上連續遇到幾個時間很長的紅燈是不是很郁悶?有時候 你可能實在受不了闖了個紅燈其實在大部分情況下問題不大如果通行的汽車很多那就不好說了因為不遵守規則的人太多都為了達到目的去走捷徑不願意等 待這樣才有了交警交警的作用就是維護這些紅綠燈的規則這些紅綠燈就像鎖一樣鎖住或延長你去目的地的時間但是如果沒有交警大家又不自由遵守紅綠燈 規則會導致什麼呢?大家想想都知道
這個系列的一篇文章中提供的事務管理器中有個鎖管理器就是這裡的交警它維護著SQLServer中的鎖前段提到的大部分情況指的就是在系統事務 量不大的時候這時候的鎖永遠不會是什麼大問題除非你知道你的系統永遠就給幾個人用否則考慮到避免系統以後的並發量上升引起數據安全與效率問題那你 得深入了解鎖機制在研究鎖之前假定你已經了解事務的ACID概念它是整個SQL Server的精髓所在如果沒有事務那就不用談鎖了除了事務需要鎖以外其他任何東西都需要這個讓SQL不自由的機制說到底鎖是一個平衡並發與數據安 全的機制如果沒有鎖任何SQL都能覆蓋其他SQL執行的數據那麼數據會出現不一致的情況如果鎖得太狠那將影響數據庫系統的並發性以及效率(包括 鎖本身帶來的額外開銷)這時候就需要去權衡SQLServer鎖管理器就充當權衡這兩者關系的角色如下圖所示
SQL Server中鎖的知識點實在太多比如鎖從模式上分為共享鎖(S)更新鎖(U)排他鎖(X)架構鎖(SchSSchM)意向鎖(IS IUIX)轉換鎖(SIXSIUUIX)大容量更新鎖(BU)鎖從粒度上分為數據庫鎖文件鎖表鎖堆鎖索引鎖頁鎖鍵鎖區鎖行 鎖應用程序鎖元數據鎖鎖之間存在兼容性問題鎖會根據情況進行升級鎖控制不好會出現死鎖悲觀鎖的隔離性未提交讀已提交讀可重復讀可序列 化樂觀鎖的隔離性讀提交快照隔離快照隔離闩(shuan)鎖隨便列下就一大堆問題要說清楚需要花很大篇幅還是抱著與前幾篇文章的風格仔 細分析一個具體的問題——鎖升級
准備
有一個動態管理視圖可以查看所有鎖sysdm_tran_locks還有一個動態管理視圖可以查看哪些請求正在阻塞其他的請求sysdm_os_waiting_tasks
什麼是鎖升級
鎖升級是指鎖的粒度由細向粗轉換如由行鎖轉成表鎖
需要鎖升級嗎?
一般來說鎖的粒度越小並發性越好但是如果去鎖定的東西多就需要的鎖越多這樣會消耗SQLServer的cpu與內存一個鎖占用內存約為 字節你算算如果用行鎖去鎖定百萬千萬的表需要多少內存而且管理鎖(創建鎖維護鎖銷毀鎖等)也是有代價的會消耗cpu 如果用一個大點的鎖就將這些百萬千萬的鎖合並成一個鎖了管理起來也方便消耗資源也小
什麼時候出現鎖升級
SQLServer意識到鎖定的頁面或行數過大的時候發生怎麼意識到過大呢?由兩種方法識別請求用於的鎖的數目超過鎖數目臨界值鎖管理器為單 獨一個查詢消耗過多的內存超過內存臨界值有其他一個超過臨界值SQLServer就會試圖升級注意這裡說的鎖數據以及內存是值由同一個查詢發生的 而不是總共的這裡說的臨界值並不是固定的SQLServer采用啟發式算法去動態調整
控制鎖升級
SQLServer提供一些可以讓我們控制鎖升級的入口在SQLServer中可以通過
alter table test
set (lock_escalation = auto|table|disable)
我們還可以通過在代碼中顯示指定pagelocktablock提示會強制SQLServer使用更粗的鎖不過這個設置不合理的話會導致並發降低建議一般情況下不用除非你很清楚這樣帶來的影響
舉例說明
建庫建表
create database Test
create table test
(
ID identity() primary key
[Name] varchar() not null default ‘’
CreatedTime datetime not null default getdate();
)
查看當前鎖情況
默認某個連接對整個數據庫有個共享鎖
循環插入幾十萬條記錄
while =
insert into test(Name) values (‘kk’)
插入時的鎖快照
從上圖中看出這個快照中有三個數據庫共享鎖一個頁級意向排他鎖一個表級意向排他鎖兩個行級排他鎖
三個數據庫共享鎖前面已經提過默認某個連接對整個數據庫有個共享鎖
一個頁級意向排他鎖一個表級意向排他鎖在頁以及表級表示資源的一部分實際已經有鎖進行保護這樣的好處允許其他請求鎖在表頁級別上進行檢查減 少不必要的更細的鎖請求提高性能比如在這種情況下如果允許alter操作那麼這個操作就會等待因為這裡有表級排他鎖它提示alter操作該表有活 動
跟蹤Lock:Escalation事件
在profiler中設置只跟蹤Lock:Escalation事件鎖升級事件
更新表中記錄
update test set name = ‘name’ where name = ‘kk’
在profiler中看到了Lock:Escalation事件被觸發
更新時的快照為(按順序)
如上圖此時update操作以排他鎖定它更新的行
如上圖此時update操作以排他鎖鎖定了整個表以架構穩定鎖(SchS)鎖定它相關的元數據表
如上圖此時釋放了對元數據表的架構穩定鎖(SchS)鎖剩下對整個表的排他鎖
從上面的分析中發現SQLServer鎖機制是有點復雜的不過也是很有意思的研究後你會發現它真的很智能今天分析就到此結束文中如有描述不當的地方歡迎指出共同進步才是硬道理(來源博客園)
From:http://tw.wingwit.com/Article/program/SQLServer/201311/22346.html