[SQL SERVER][Performance]淺談鎖定擴大

[SQL SERVER][Performance]淺談鎖定擴大

什麼是鎖定擴大?

鎖定擴大就是把低階層鎖定升級到高階層鎖定的過程,

這樣可以減少系統負擔(記憶體量變少),

但可能會增加並行爭用的可能性(Blocking變多)。

 

觸發條件

image

(擷取BOL)

 

效能考量

SQL Server每一個鎖定都必須要耗費記憶體,所以鎖定的數量是和記憶體用量成正比,

為了解決這樣的問題,SQL2005新增鎖定擴大的機制,只要達到任一上述觸發條件,

馬上將鎖定擴大升級,這樣一來可以釋放先前低階層鎖定(row lock)記憶體用量,

鎖定擴大(table lock)後記憶體用量也相對減少,但鎖定擴大也帶來並行爭用的可能性,

即是封鎖(Blocking)變多了(你絕對不希望使用者查詢資料表時...一直....等等等),

如果鎖定擴大的次數太頻繁,無疑也將對效能造成一定的影響,

這時就要考慮減少鎖定擴大次數,下面我將透過範例來實際了解鎖定擴大過程。

 

connection1執行以下TSQL

begin tran
update top(4000) t1
set c2=c2+'x'

 

查詢鎖定類型和物件

 

 

select resource_type,resource_associated_entity_id,request_mode,
request_type,request_status 
from sys.dm_tran_locks 
where resource_database_id = 7
and request_session_id=54

image

可以看到產生Key Lock(row level) 數量相當多 ,

這時使用者可以查詢未鎖定的資料列,

接下來先 rollback 後並將數量改成5000。

 

begin tran
update top(5000) t1
set c2=c2+'x'

 

 

image

由於觸發了鎖定擴大條件,所以鎖定層級由 Key(row level) 變成 Object (table level),

並釋放之前低階層鎖定記憶體資源,但由於鎖定擴大到資料表,

這時使用者必須等待該交易完成後才可查詢該資料表。

 

如何減少鎖定擴大

1.設定追蹤旗標(trace flag)(不建議)

 

 

1211

image

(擷取BOL)

 

1224

image

(擷取BOL)

 

2. 修改資料表 LOCK_ESCALATION = DISABLE(SQL2008之後版本才支援)

image

(擷取BOL)

 

關閉鎖定擴大
alter table t1 set (LOCK_ESCALATION=disable)

 

 

 

3.使用資料列版本控制

參考選擇以資料列版本控制為基礎的隔離等級

image

(擷取BOL)

 

ps:為了要避開封鎖問題,所以查詢可能會加上with(nolock),但with(nolock)還請小心服用

 

 

 

參考

保留鎖定組態選項預設值

Database Engine 中的鎖定

使用資料列版本控制式的隔離等級

調整交易隔離等級

鎖定擴大 (Database Engine)

SQL Server 2008 Locking

SQL Server 2008: Lock escalation changes