I was faced with an interesting situation yesterday where a customer had created a blocking chain on their SQL Azure database. The scenario they described was:
A query took out and held a lock on object but the client connection closed and orphaned the session on the SQL Azure database. This resulted in other queries trying to access the object being blocked and timing out (even a SELECT *).
Given we do not have any graphical tools in SSMS to see current activity when you connect to a SQL Azure database, this offers a challenge for those that are use to going to Activity Monitor or the Reports to view this sort of information. Thankfully most of DMV's and DMF's have made their way into support on SQL Azure.
To troubleshoot the above scenario we then used the following queries to identify the culprit and eventually terminate it with the only option available.... KILL [spid]. To demonstrate this I have created the scenario on my Azure database through the use of PowerShell (but i am not sharing that as it is bad practice). The good news is that these queries will also work for your on-premise environments.
TSQL to identify the Blockers and Victims
The output of this query looks then like the following where you can clearly see the blocker and it's victims (in fact this example then has a 2nd layer of blocking).
TSQL to view the established locks within the current database
The output of this query shows the various locks which have been established by each session (one-to-many in sessions-to-locks). From here we can see which locks will have taken priority and potentially blocking more queries in the future.
So while you may not have a graphical view of this information we can definitely use our trusted DMV's and DMF's to gain access to the relevant data. Who knows with the rate of change it can surely only be a matter of time until Activity Monitor and the standard reports are available to us in SSMS for SQL Azure.
Legal Stuff: As always the contents of this blog is provided “as-is”. The information, opinions and views expressed are those of the author and do not necessarily state or reflect those of any other company with affiliation to the products discussed. This includes any URLs or Tools. The author does not accept any responsibility from the use of the information or tools mentioned within this blog, and recommends adequate evaluation against your own requirements to measure suitability.
A query took out and held a lock on object but the client connection closed and orphaned the session on the SQL Azure database. This resulted in other queries trying to access the object being blocked and timing out (even a SELECT *).
Given we do not have any graphical tools in SSMS to see current activity when you connect to a SQL Azure database, this offers a challenge for those that are use to going to Activity Monitor or the Reports to view this sort of information. Thankfully most of DMV's and DMF's have made their way into support on SQL Azure.
To troubleshoot the above scenario we then used the following queries to identify the culprit and eventually terminate it with the only option available.... KILL [spid]. To demonstrate this I have created the scenario on my Azure database through the use of PowerShell (but i am not sharing that as it is bad practice). The good news is that these queries will also work for your on-premise environments.
TSQL to identify the Blockers and Victims
WITH Blockers AS (select DISTINCT blocking_session_id as session_id from sys.dm_exec_requests where blocking_session_id > 0 ) SELECT 'Blocker' as type_desc , sys.dm_exec_sessions.session_id , sys.dm_exec_requests.start_time , sys.dm_exec_requests.status , sys.dm_exec_requests.command , sys.dm_exec_requests.wait_type , sys.dm_exec_requests.wait_time , sys.dm_exec_requests.blocking_session_id , '' AS stmt_text FROM sys.dm_exec_sessions LEFT JOIN sys.dm_exec_requests ON sys.dm_exec_requests.session_id = sys.dm_exec_sessions.session_id INNER JOIN Blockers ON Blockers.session_id = sys.dm_exec_sessions.session_id UNION SELECT 'Victim' as type_desc , sys.dm_exec_sessions.session_id , sys.dm_exec_requests.start_time , sys.dm_exec_requests.status , sys.dm_exec_requests.command , sys.dm_exec_requests.wait_type , sys.dm_exec_requests.wait_time , sys.dm_exec_requests.blocking_session_id , ST.text AS stmt_text FROM sys.dm_exec_sessions INNER JOIN sys.dm_exec_requests ON sys.dm_exec_requests.session_id = sys.dm_exec_sessions.session_id CROSS APPLY SYS.DM_EXEC_SQL_TEXT(sys.dm_exec_requests.sql_handle) AS ST WHERE blocking_session_id > 0
The output of this query looks then like the following where you can clearly see the blocker and it's victims (in fact this example then has a 2nd layer of blocking).
TSQL to view the established locks within the current database
SELECT (CASE sys.dm_tran_locks.request_session_id WHEN -2 THEN 'ORPHANED DISTRIBUTED TRANSACTION' WHEN -3 THEN 'DEFERRED RECOVERY TRANSACTION' ELSE sys.dm_tran_locks.request_session_id END) AS session_id , DB_NAME(sys.dm_tran_locks.resource_database_id) AS database_name , sys.objects.name AS locked_obj_name , sys.dm_tran_locks.resource_type AS locked_resource , sys.dm_tran_locks.request_mode AS lock_type , ST.text AS stmt_text , sys.dm_exec_sessions.login_name AS login_name , sys.dm_exec_sessions.host_name AS host_name , sys.dm_tran_locks.request_status as request_status FROM sys.dm_tran_locks JOIN sys.objects ON sys.objects.object_id = sys.dm_tran_locks.resource_associated_entity_id JOIN sys.dm_exec_sessions ON sys.dm_exec_sessions.session_id = sys.dm_tran_locks.request_session_id JOIN sys.dm_exec_connections ON sys.dm_exec_connections.session_id = sys.dm_exec_sessions.session_id CROSS APPLY SYS.DM_EXEC_SQL_TEXT(sys.dm_exec_connections.most_recent_sql_handle) AS st WHERE sys.dm_tran_locks.resource_database_id = DB_ID() ORDER BY sys.dm_tran_locks.request_session_id
The output of this query shows the various locks which have been established by each session (one-to-many in sessions-to-locks). From here we can see which locks will have taken priority and potentially blocking more queries in the future.
So while you may not have a graphical view of this information we can definitely use our trusted DMV's and DMF's to gain access to the relevant data. Who knows with the rate of change it can surely only be a matter of time until Activity Monitor and the standard reports are available to us in SSMS for SQL Azure.
Legal Stuff: As always the contents of this blog is provided “as-is”. The information, opinions and views expressed are those of the author and do not necessarily state or reflect those of any other company with affiliation to the products discussed. This includes any URLs or Tools. The author does not accept any responsibility from the use of the information or tools mentioned within this blog, and recommends adequate evaluation against your own requirements to measure suitability.
No comments:
Post a Comment