1. 程式人生 > >SqlServer 表選項LOCK_ESCALATION對分割槽的影響

SqlServer 表選項LOCK_ESCALATION對分割槽的影響

SqlServer 使用鎖管理器跟蹤資料庫物件是否被鎖住.通常一個查詢將鎖住一行或者一頁,當鎖超過一定範圍之後,SqlServer嘗試將鎖升級為表鎖來保證對記憶體的使用.鎖升級有時會導致堵塞或者死鎖.在SQL Server profiler中我們可以用[Lock:Escalation]事件來跟蹤鎖的升級.



在SQL Server 2005 中,可以使用跟蹤標誌 1211 來禁用整個例項中的鎖升級.而在SQL Server 2008中,可以使用新的選擇來禁止某個表的鎖升級

ALTER TABLE SET (LOCK_ECALATION = AUTO | TABLE | DISABLE)

AUTO

此選項允許 SQL Server 資料庫引擎選擇適合於表架構的鎖升級粒度。

(AUTO:如表已分割槽,將使用分割槽的hobt鎖,但併發情況增加。)

如果該表已分割槽,則允許將鎖升級到分割槽。 鎖升級到分割槽級別之後,該鎖以後將不會升級到 TABLE 粒度。

如果該表未分割槽,則會將鎖升級到 TABLE 粒度

TABLE

無論表是否已分割槽,都會在表級粒度完成鎖升級。 預設值為 TABLE

DISABLE

在大多數情況下禁止鎖升級。 表級別的鎖未完全禁止。

例如,當掃描在可序列化隔離級別下沒有聚集索引的表時,資料庫引擎必須使用表鎖來保證資料的完整性。


經過幾次插入資料測試,使我要更改的這個條件的資料達到6500行,這樣才進行鎖升級。否則鍵鎖和頁鎖非常多。

--分割槽1:6500行
select COUNT(*) from dbo.AABB where $partition.pf_sid(sid)=1

--先測試表:TABLE
ALTER TABLE dbo.AABB SET (LOCK_ESCALATION = TABLE);

begin tran 
	update dbo.AABB set num=1
	where sid=0x0105000000000005150000002B5CA2768377FDF37E993215F4010000

	SELECT resource_type,resource_subtype,resource_description,request_mode,resource_associated_entity_id
	from sys.dm_tran_locks 
	where resource_database_id=DB_ID() and request_session_id=@@SPID  
	order by resource_type,resource_description
rollback tran

可以看到,物件表使用了排他鎖,這樣整個表都不能訪問了!
--再測試表:AUTO
ALTER TABLE dbo.AABB SET (LOCK_ESCALATION = AUTO);


這才是正常的!!只鎖定其中1個分割槽,其他分割槽還可以訪問和修改!(關聯的分割槽id不一樣,因測試換了幾次表)

當我們把表分割槽的時候,設定表選項 ALTER TABLE dbo.[tableName] SET (LOCK_ESCALATION = AUTO);這樣可以在不同分割槽並行訪問!

附加指令碼:

--  檢視分割槽情況  
select OBJECT_NAME(object_id) as tab,COUNT(partition_number) as part     
from sys.partitions     
where index_id in(0,1)    
and OBJECT_NAME(object_id) not like 'conflict%'    
and OBJECT_NAME(object_id) not like 'sys%'    
and OBJECT_NAME(object_id) not like 'MS%'   
group by object_id 
order by tab


  
--  批量設定表選項——啟用鎖升級到分割槽  
DECLARE @tbName VARCHAR(50)  
DECLARE cur SCROLL CURSOR   
FOR       
    select OBJECT_NAME(object_id) as tab  
    from sys.partitions     
    where index_id in(0,1)    
    and OBJECT_NAME(object_id) not like 'conflict%'    
    and OBJECT_NAME(object_id) not like 'sys%'  
	and OBJECT_NAME(object_id) not like 'MS%'  
    group by object_id   
    having COUNT(partition_number)>1  
    order by tab  
OPEN cur  
FETCH NEXT FROM cur INTO @tbName  
WHILE @@FETCH_STATUS = 0  
BEGIN  
    PRINT ('ALTER TABLE [dbo].['+@tbName+'] SET (LOCK_ESCALATION = AUTO); ')  
    FETCH NEXT FROM cur INTO @tbName  
END  
CLOSE cur  
DEALLOCATE cur  

附加說明:

觸發鎖升級:(資料庫引擎不會將行鎖或鍵範圍鎖升級到頁鎖,而是將它們直接升級到表鎖)

A 單個 Transact-SQL 語句在單個無分割槽表或索引上獲得至少 5,000 個鎖

B 單個 Transact-SQL 語句在已分割槽表的單個分割槽上獲得至少 5,000 個鎖,並且 ALTER TABLE SET LOCK_ESCALATION 選項設為 AUTO

C 資料庫引擎例項中的鎖的數量超出了記憶體或配置閾值

D 如果由於鎖衝突導致無法升級鎖,則資料庫引擎每當獲取 1,250 個新鎖時便會觸發鎖升級