Getting Started with Adobe After Effects - Part 6: Motion Blur


Upload Image Close it
Select File

Random thoughts about SQL Server
Browse by Tags · View All
BRH 10
tsql 8
sqlserver 8
#SQLServer 7
denali 6
BR 4
SQLServerPedia Syndication 4
SQL Server 4
#TSQL 3
2012 2

Archive · View All
March 2011 7
January 2012 2
August 2011 1
May 2011 1
April 2011 1
April 2010 1

Sankar Reddy's Blog

Interrogating Lock Escalation thresholds – Part 1

Mar 20 2011 5:26AM by Sankar   

Introduction

Locking in SQL Server is a very important aspect but misunderstood by many folks and there are many myths that go around this topic. SQL Server provides few knobs to control the behavior of locking to some degree but for the end user perspective it is completely opaque, how SQL Server manages locks when queries are executed.

In this series, I will take some facts around locking and interrogate them to shed more light and quash some misconceptions. For this post, we will look at the some Lock Escalation thresholds. To get a primer on this topic, a good place to start is looking at the below links. Basically, Lock Escalation is triggered automatically by SQL Server when the cost of maintaining many fine-grain locks increases system overhead and changes them to coarse-grain locks.

Lock Escalation in SQL Server 2005

Lock Escalation (Database Engine)

http://blogs.msdn.com/b/sqlcat/archive/tags/concurrency/

Background

SQL Server uses locks to synchronize the data modifications when many users are trying to access the data concurrently. But locks come with a cost around 100 bytes per each lock, while many fine grain locks improve the concurrency only at the additional cost of system overhead maintaining those locks. There is potential of exhausting system resources essentially bringing the server down if correct locking granularity is NOT applied. To avoid situations like this, SQL Server automatically escalates the locks from many fine grain locks to fewer coarser locks thus improving the overall system performance.

Picture below (taken from BOL) lists some details when Lock Escalation is triggered automatically by SQL Server. For this post, we will look at the first statement below which specifies lock escalation is triggered when at-least 5000 locks are required by a single SQL statement on a single non-partitioned table. The misconception I heard around this statement is SQL Server does lock escalation as soon as 5000 locks are reached.

Lock Escalation thresholds from BOL

Ref: msdn.microsoft.com/en-us/library/ms184286(v=SQL.105).aspx

Test + sys.dm_tran_locks

We will go over a simple example and look at the lock escalation details in different ways. Lets create a table and load 50000 rows into the table.

--Create Table
IF OBJECT_ID('dbo.TestTable', 'U') IS NOT NULL
	DROP TABLE dbo.TestTable
GO
CREATE TABLE dbo.TestTable (
	c1 BIGINT IDENTITY(1,1)
	, c2 CHAR(200) NOT NULL
	, CONSTRAINT PK_TestTable PRIMARY KEY (c1)
)
GO
--Load data
;WITH
   X1 AS ( SELECT name AS C FROM sys.objects)
  , X2 AS ( SELECT DISTINCT name AS C FROM sys.columns)
  , X3 AS ( SELECT REVERSE(name) AS C FROM sys.objects)
INSERT dbo.TestTable (c2)
SELECT TOP 50000
   X1.C + ' ' + X2.C + ' ' + X3.C AS C1
FROM X1 CROSS JOIN X2 CROSS JOIN X3
GO

Nothing else is happening on the server and lets try to update 4999 records as the first step and peek into the number of locks acquired and the type of locks using the sys.dm_tran_locks DMV. Note that querying this DMV in a production box may take lot of resources and NOT a good choice unless troubleshooting some issues.

--Try 4999
BEGIN TRAN

UPDATE dbo.TestTable WITH (ROWLOCK)
	SET c2 = c1
	WHERE c1 <= 4999

SELECT resource_type, request_mode, COUNT(1) AS [This Many Locks]
FROM sys.dm_tran_locks WHERE request_session_id = @@SPID
GROUP BY resource_type, request_mode

ROLLBACK TRAN

Picture below shows the type, lock mode and the number of locks taken for updating 4999 records.

Locks held when updating 4999 records

Now lets try to update 5000 records, the minimum threshold for triggering lock escalation and check if the lock escalation happens.

--Try 5000
BEGIN TRAN

UPDATE dbo.TestTable WITH (ROWLOCK)
	SET c2 = c1
	WHERE c1 <= 5000

SELECT resource_type, request_mode, COUNT(1) AS [This Many Locks]
FROM sys.dm_tran_locks WHERE request_session_id = @@SPID
GROUP BY resource_type, request_mode

ROLLBACK TRAN

As you see below, lock escalation didn’t happened at the minimum threshold of 5000 locks and still using row locks.

Locks held when updating 5000 records

After some trail and error, it seems 6084 is the magic number for triggering lock escalation on this table.

--Try 6084, this is the magic number for this table
BEGIN TRAN

UPDATE dbo.TestTable WITH (ROWLOCK)
	SET c2 = c1
	WHERE c1 <= 6084

SELECT resource_type, request_mode, COUNT(1) AS [This Many Locks]
FROM sys.dm_tran_locks WHERE request_session_id = @@SPID
GROUP BY resource_type, request_mode

ROLLBACK TRAN
GO

Lock Escalation happened for updating 6084 rows

From the above tests, it is clear that lock escalation doesn’t happen at the minimum threshold of 5000 locks always and might happen after crossing over the threshold. Another important point to note is that lock escalation doesn’t happen from rows to page and then page to table. Its usually happens from either rows to table or page to table. One key information missing from the above is how do we know if the lock escalation happened because the threshold of at-least 5000 locks and NOT some memory threshold?

Using Lock Escalation Trace event

Now, lets look at the data from the same above tests especially for the update when lock escalation is triggered but from a different method using the Lock Escalation Trace Event.

Lock Escalation using Trace Event

Using Extended events

That’s good information but isn’t using Trace Events to capture this information expensive? Yes, let’s try another method to look at this using XEvents. Extended Events are the future of monitoring information in SQL Server going forward as they are lite weight, asynchronous and scales well compared to the Trace Events.

--Now, create a session and captures relevant information
--Use asynchronous file target
CREATE EVENT SESSION TrackLockEscalation ON SERVER
ADD EVENT sqlserver.lock_escalation(
   ACTION (sqlserver.sql_text, sqlserver.database_name, sqlserver.client_hostname, sqlserver.username
			, sqlserver.tsql_stack, sqlserver.server_instance_name, sqlserver.session_id)
   )
ADD TARGET Package0.asynchronous_file_target
( SET filename = 'C:\SQLServer\XEvents\TrackLockEscalation.xel'
		, metadatafile = 'C:\SQLServer\XEvents\TrackLockEscalation.mta')
WITH (MAX_MEMORY=4096 KB
		, EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS
		, MAX_DISPATCH_LATENCY=30 SECONDS
		, MAX_EVENT_SIZE=0 KB
		, MEMORY_PARTITION_MODE=NONE
		, TRACK_CAUSALITY=OFF
		, STARTUP_STATE=OFF)
GO

--Now, that the event session for tracking connection pooling
ALTER EVENT SESSION TrackLockEscalation
ON SERVER
STATE=START
GO

 

--Try 6084, this is the magic number for this table
BEGIN TRAN

UPDATE dbo.TestTable WITH (ROWLOCK)
	SET c2 = c1
	WHERE c1 <= 6084

SELECT resource_type, request_mode, COUNT(1) AS [This Many Locks]
FROM sys.dm_tran_locks WHERE request_session_id = @@SPID
GROUP BY resource_type, request_mode

ROLLBACK TRAN
GO

 

--Wait for few minutes to capture some activity and stop the session
ALTER EVENT SESSION TrackLockEscalation
ON SERVER
STATE=STOP
GO

--Go, clean up
DROP EVENT SESSION TrackLockEscalation ON SERVER
GO

--Lets parse the xml data in a easy to read format
SELECT
	FinalData.R.value ('@name', 'nvarchar(50)') AS EventName
	,  FinalData.R.value ('(action[@name="sql_text"]/value)[1]', 'nvarchar(2000)') AS [SQL Text]
	, FinalData.R.value ('(data[@name="escalation_cause"]/value)[1]', 'varchar(50)')
		+ ' - ' +
		FinalData.R.value ('(data[@name="escalation_cause"]/text)[1]', 'varchar(50)')
			AS [Lock Escalation cause]
	, FinalData.R.value ('(data[@name="hobt_lock_count"]/value)[1]', 'varchar(50)')
			AS [IntegerData]
	, FinalData.R.value ('(data[@name="escalated_lock_count"]/value)[1]', 'varchar(50)')
			AS [IntegerData2]
	, FinalData.R.value ('(data[@name="mode"]/value)[1]', 'varchar(50)')
		+ ' - ' +
		FinalData.R.value ('(data[@name="mode"]/text)[1]', 'varchar(50)')
			AS [Resource Mode]
	, FinalData.R.value ('(data[@name="resource_type"]/value)[1]', 'varchar(50)')
		+ ' - ' +
		FinalData.R.value ('(data[@name="resource_type"]/text)[1]', 'varchar(50)')
			AS [Resource Type]
FROM (
SELECT
    CAST(event_data AS XML) AS xmldata
 FROM sys.fn_xe_file_target_read_file
 (
	'C:\SQLserver\XEvents\TrackLockEscalation*.xel'
	, 'C:\SQLserver\XEvents\TrackLockEscalation*mta'
	, null
	, null
)) AsyncFileData
CROSS APPLY xmldata.nodes ('//event') AS FinalData (R)

We essentially got the same data as we got from the Lock Escalation trace event.

Lock Escalation using Extended Events

Key points

  • Lock Escalation doesn’t happen at the minimum threshold of 5000 locks always.
  • Escalation happens from rows to table or page to table only.
  • ROWLOCK hints are NOT always honoured.


Republished from Sankar Reddy [39 clicks].  Read the original version here [32134 clicks].

Sankar
113 · 1% · 454
0
Liked
 
0
Lifesaver
 
0
Refreshed
 
0
Learned
 
0
Incorrect



Submit

1  Comments  

  • Very interesting and helpful. What version was this based on? I could not find the sqlserver.lock_escalation event in SQL2008R2 event class

    commented on Aug 2 2012 9:34AM
    SQLGuruToo
    2704 · 0% · 3

Your Comment


Sign Up or Login to post a comment.

    Copyright © Rivera Informatic Private Ltd Contact us      Privacy Policy      Terms of use      Report Abuse      Advertising      [ZULU1097]