Ver Fonte

Made Running-Blocked_Processes into usp_WhatsUp

Returns running sessions/requests; blocking information; sessions that have been granted locks or waiting for locks; and optionally SP/Query/Trigger/Function execution stats
pmasl há 6 anos atrás
pai
commit
43ceeb1556

+ 0 - 7
Running-Blocked-Processes/README.md

@@ -1,7 +0,0 @@
-**Purpose:** Returns a snapshot on running sessions/requests; blocking information; sessions that have been granted locks or waiting for locks; SPs stats.
-
-In the output, you will find the following information in 4 sections:
--  Uptime Information
--  Running Sessions/Requests Report including resource usage, running statement, execution plan, blocking resource, waits and other relevant information.
--  Waiter and Blocking Report, including information on head blocker and blocking chains.
--  Stored procedure execution statistics.

+ 35 - 0
usp_WhatsUp/README.md

@@ -0,0 +1,35 @@
+** usp_whatsup**
+
+**Purpose:** Understand what's up with your SQL Server and get all sorts of useful troubleshooting information such as:
+-  A snapshot on running sessions/requests; 
+-  Current blocking information; 
+-  Optionally, SP/Query/Trigger/Function execution stats.
+
+In the output, you will find the following information in 6 sections:
+-  Uptime Information
+-  Running Sessions/Requests Report including resource usage, running statement, execution plan, blocking resource, waits and other relevant information.
+-  Waiter and Blocking Report, including information on head blocker and blocking chains.
+-  Stored procedure execution statistics.
+-  Query execution statistics.
+-  Trigger execution statistics.
+-  Function execution statistics.
+
+**Change log:**
+-  2012-09-10 Added extra information
+-  2013-02-02 Added extra information
+-  2013-04-12 Added page type information (PFS; GAM or SGAM) when wait type is PAGELATCH_ or PAGEIOLATCH_ .
+-  2013-05-23 Fixed parse page issue
+-  2013-09-16 Added mem grants information
+-  2013-10-17 Added statements to blocking and blocked sections, fixed head blocker info 
+-  2013-12-09 Fixed blocking section showing non-blocked sessions also
+-  2014-02-04 Fixed conversion issue with blocking section
+-  2014-04-09 Added information to blocking section, and fixed conversion issue
+-  2014-12-09 Handle illegal characters in XML conversion
+-  11/16/2016 Added support for SQL Server 2016 SP1 and live query plan snapshot.
+-  12/2/2016 Fixed transport-level error issue with SQL Server 2016 SP1.
+-  2/16/2016 Added NOLOCK hints.
+-  3/28/2017 Fixed missing characters in offset fetches.
+-  10/11/2017 Commented out stored procedure/query stats section to optimize for in-flight requests.
+-  10/20/2017 Added Query stats section and support for sys.dm_exec_query_statistics_xml.
+-  04/02/2019 Added support for sys.dm_exec_query_plan_stats and trigger/function stats section.
+-  04/08/2019 Made into a stored procedure usp_whatsup instead of adhoc script for ease of use.

+ 179 - 204
Running-Blocked-Processes/view_Running_Blocked_processes.sql → usp_WhatsUp/usp_whatsup.sql

@@ -1,60 +1,44 @@
 -- 2012-04-07 Pedro Lopes (Microsoft) (http://aka.ms/tigertoolbox/)
---
--- Returns running sessions/requests; blocking information; sessions that have been granted locks or waiting for locks; SPs stats.
---
--- 2012-09-10 Added extra information
--- 2013-02-02 Added extra information
--- 2013-04-12 Added page type information (PFS; GAM or SGAM) when wait type is PAGELATCH_ or PAGEIOLATCH_ .
--- 2013-05-23 Fixed parse page issue
--- 2013-09-16 Added mem grants information
--- 2013-10-17 Added statements to blocking and blocked sections, fixed head blocker info 
--- 2013-12-09 Fixed blocking section showing non-blocked sessions also
--- 2014-02-04 Fixed conversion issue with blocking section
--- 2014-04-09 Added information to blocking section, and fixed conversion issue
--- 2014-12-09 Handle illegal characters in XML conversion
--- 11/16/2016 Added support for SQL Server 2016 SP1 and live query plan snapshot.
--- 12/2/2016 Fixed transport-level error issue with SQL Server 2016 SP1.
--- 2/16/2016 Added NOLOCK hints.
--- 3/28/2017 Fixed missing characters in offset fetches.
--- 10/11/2017 Commented out stored procedure/query stats section to optimize for in-flight requests.
--- 10/20/2017 Added Query stats section and support for sys.dm_exec_query_statistics_xml.
--- 04/02/2019 Added support for sys.dm_exec_query_plan_stats and trigger/function stats section.
 
+CREATE PROCEDURE usp_whatsup @uptime bit = 1, @requests bit = 1, @blocking bit = 1, @spstats bit = 0, @qrystats bit = 0, @trstats bit = 0, @fnstats bit = 0
+AS
 
-/*
-NOTE: Some sections are commented out for a quick default insight to in-flight requests. 
-	Uncomment section you would like to execute as well for a more holistic approach on executions. 
-*/
+-- Returns running sessions/requests; blocking information; sessions that have been granted locks or waiting for locks; and optionally SP/Query/Trigger/Function execution stats.
 
 SET NOCOUNT ON;
-DECLARE @UpTime VARCHAR(12), @StartDate DATETIME, @sqlmajorver int, @sqlcmd NVARCHAR(500), @params NVARCHAR(500)
-SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) & 0xff);
 
-IF @sqlmajorver = 9
-BEGIN
-	SET @sqlcmd = N'SELECT @StartDateOUT = login_time, @UpTimeOUT = DATEDIFF(mi, login_time, GETDATE()) FROM master..sysprocesses WHERE spid = 1';
-END
-ELSE
+DECLARE @sqlmajorver int, @sqlbuild int, @sqlcmd NVARCHAR(500), @params NVARCHAR(500)
+SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) & 0xff);
+SELECT @sqlbuild = CONVERT(int, @@microsoftversion & 0xffff);
+	
+IF @uptime = 1
 BEGIN
-	SET @sqlcmd = N'SELECT @StartDateOUT = sqlserver_start_time, @UpTimeOUT = DATEDIFF(mi,sqlserver_start_time,GETDATE()) FROM sys.dm_os_sys_info';
-END
+	DECLARE @UpTime VARCHAR(12), @StartDate DATETIME, 
+
+	IF @sqlmajorver = 9
+	BEGIN
+		SET @sqlcmd = N'SELECT @StartDateOUT = login_time, @UpTimeOUT = DATEDIFF(mi, login_time, GETDATE()) FROM master..sysprocesses WHERE spid = 1';
+	END
+	ELSE
+	BEGIN
+		SET @sqlcmd = N'SELECT @StartDateOUT = sqlserver_start_time, @UpTimeOUT = DATEDIFF(mi,sqlserver_start_time,GETDATE()) FROM sys.dm_os_sys_info';
+	END
 
-SET @params = N'@StartDateOUT DATETIME OUTPUT, @UpTimeOUT VARCHAR(12) OUTPUT';
+	SET @params = N'@StartDateOUT DATETIME OUTPUT, @UpTimeOUT VARCHAR(12) OUTPUT';
 
-EXECUTE sp_executesql @sqlcmd, @params, @StartDateOUT=@StartDate OUTPUT, @UpTimeOUT=@UpTime OUTPUT;
+	EXECUTE sp_executesql @sqlcmd, @params, @StartDateOUT=@StartDate OUTPUT, @UpTimeOUT=@UpTime OUTPUT;
 
-SELECT 'Uptime_Information' AS [Information], GETDATE() AS [Current_Time], @StartDate AS Last_Startup, CONVERT(VARCHAR(4),@UpTime/60/24) + 'd ' + CONVERT(VARCHAR(4),@UpTime/60%24) + 'h ' + CONVERT(VARCHAR(4),@UpTime%60) + 'm' AS Uptime
+	SELECT 'Uptime_Information' AS [Information], GETDATE() AS [Current_Time], @StartDate AS Last_Startup, CONVERT(VARCHAR(4),@UpTime/60/24) + 'd ' + CONVERT(VARCHAR(4),@UpTime/60%24) + 'h ' + CONVERT(VARCHAR(4),@UpTime%60) + 'm' AS Uptime
 
---SELECT DATEDIFF(hh,'2011-09-08 11:35:00',GETDATE()) AS since_lst_clear 
-GO
+	--SELECT DATEDIFF(hh,'2011-09-08 11:35:00',GETDATE()) AS since_lst_clear 
+END;
 
 -- Running Sessions/Requests Report
-DECLARE @sqlmajorver int, @sqlbuild int, @sqlcmd VARCHAR(8000)
-SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) & 0xff);
-SELECT @sqlbuild = CONVERT(int, @@microsoftversion & 0xffff);
-IF @sqlmajorver = 9
+IF @requests = 1
 BEGIN
-	SELECT @sqlcmd = N'SELECT ''Requests'' AS [Information], es.session_id, DB_NAME(er.database_id) AS [database_name], OBJECT_NAME(qp.objectid, qp.dbid) AS [object_name], -- NULL if Ad-Hoc or Prepared statements
+	IF @sqlmajorver = 9
+	BEGIN
+		SELECT @sqlcmd = N'SELECT ''Requests'' AS [Information], es.session_id, DB_NAME(er.database_id) AS [database_name], OBJECT_NAME(qp.objectid, qp.dbid) AS [object_name], -- NULL if Ad-Hoc or Prepared statements
 	(SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
 		qt.text,
 		NCHAR(1),N''?''),NCHAR(2),N''?''),NCHAR(3),N''?''),NCHAR(4),N''?''),NCHAR(5),N''?''),NCHAR(6),N''?''),NCHAR(7),N''?''),NCHAR(8),N''?''),NCHAR(11),N''?''),NCHAR(12),N''?''),NCHAR(14),N''?''),NCHAR(15),N''?''),NCHAR(16),N''?''),NCHAR(17),N''?''),NCHAR(18),N''?''),NCHAR(19),N''?''),NCHAR(20),N''?''),NCHAR(21),N''?''),NCHAR(22),N''?''),NCHAR(23),N''?''),NCHAR(24),N''?''),NCHAR(25),N''?''),NCHAR(26),N''?''),NCHAR(27),N''?''),NCHAR(28),N''?''),NCHAR(29),N''?''),NCHAR(30),N''?''),NCHAR(31),N''?'') 
@@ -123,10 +107,10 @@ FROM sys.dm_exec_requests (NOLOCK) er
 	OUTER APPLY sys.dm_exec_query_plan(er.plan_handle) qp
 WHERE er.session_id <> @@SPID AND es.is_user_process = 1
 ORDER BY er.total_elapsed_time DESC, er.logical_reads DESC, [database_name], session_id'
-END
-ELSE IF @sqlmajorver IN (10,11,12) OR (@sqlmajorver = 13 AND @sqlbuild < 4000)
-BEGIN
-	SET @sqlcmd = N';WITH tsu AS (SELECT session_id, SUM(user_objects_alloc_page_count) AS user_objects_alloc_page_count, 
+	END
+	ELSE IF @sqlmajorver IN (10,11,12) OR (@sqlmajorver = 13 AND @sqlbuild < 4000)
+	BEGIN
+		SET @sqlcmd = N';WITH tsu AS (SELECT session_id, SUM(user_objects_alloc_page_count) AS user_objects_alloc_page_count, 
 SUM(user_objects_dealloc_page_count) AS user_objects_dealloc_page_count, 
 SUM(internal_objects_alloc_page_count) AS internal_objects_alloc_page_count, 
 SUM(internal_objects_dealloc_page_count) AS internal_objects_dealloc_page_count FROM sys.dm_db_task_space_usage (NOLOCK) GROUP BY session_id)
@@ -207,10 +191,10 @@ FROM sys.dm_exec_requests (NOLOCK) er
 	OUTER APPLY sys.dm_exec_query_plan(er.plan_handle) qp
 WHERE er.session_id <> @@SPID AND es.is_user_process = 1
 ORDER BY er.total_elapsed_time DESC, er.logical_reads DESC, [database_name], session_id'
-END
-ELSE IF (@sqlmajorver = 13 AND @sqlbuild > 4000) OR @sqlmajorver = 14 OR (@sqlmajorver = 15 AND @sqlbuild < 1400)
-BEGIN
-	SELECT @sqlcmd = N'WITH tsu AS (SELECT session_id, SUM(user_objects_alloc_page_count) AS user_objects_alloc_page_count, 
+	END
+	ELSE IF (@sqlmajorver = 13 AND @sqlbuild > 4000) OR @sqlmajorver = 14 OR (@sqlmajorver = 15 AND @sqlbuild < 1400)
+	BEGIN
+		SELECT @sqlcmd = N'WITH tsu AS (SELECT session_id, SUM(user_objects_alloc_page_count) AS user_objects_alloc_page_count, 
 SUM(user_objects_dealloc_page_count) AS user_objects_dealloc_page_count, 
 SUM(internal_objects_alloc_page_count) AS internal_objects_alloc_page_count, 
 SUM(internal_objects_dealloc_page_count) AS internal_objects_dealloc_page_count FROM sys.dm_db_task_space_usage (NOLOCK) GROUP BY session_id)
@@ -293,10 +277,10 @@ FROM sys.dm_exec_requests (NOLOCK) er
 	OUTER APPLY sys.dm_exec_query_statistics_xml(er.session_id) qes
 WHERE er.session_id <> @@SPID AND es.is_user_process = 1
 ORDER BY er.total_elapsed_time DESC, er.logical_reads DESC, [database_name], session_id'
-END
-ELSE IF (@sqlmajorver = 15 AND @sqlbuild >= 1400) OR @sqlmajorver > 15 
-BEGIN
-	SELECT @sqlcmd = N'WITH tsu AS (SELECT session_id, SUM(user_objects_alloc_page_count) AS user_objects_alloc_page_count, 
+	END
+	ELSE IF (@sqlmajorver = 15 AND @sqlbuild >= 1400) OR @sqlmajorver > 15 
+	BEGIN
+		SELECT @sqlcmd = N'WITH tsu AS (SELECT session_id, SUM(user_objects_alloc_page_count) AS user_objects_alloc_page_count, 
 SUM(user_objects_dealloc_page_count) AS user_objects_dealloc_page_count, 
 SUM(internal_objects_alloc_page_count) AS internal_objects_alloc_page_count, 
 SUM(internal_objects_dealloc_page_count) AS internal_objects_dealloc_page_count FROM sys.dm_db_task_space_usage (NOLOCK) GROUP BY session_id)
@@ -374,142 +358,141 @@ FROM sys.dm_exec_requests (NOLOCK) er
 	OUTER APPLY sys.dm_db_page_info(pc.db_id, pc.file_id, pc.page_id, ''LIMITED'') pi
 WHERE er.session_id <> @@SPID AND es.is_user_process = 1
 ORDER BY er.total_elapsed_time DESC, er.logical_reads DESC, [database_name], session_id'
-END
---PRINT @sqlcmd
-EXECUTE (@sqlcmd)
-GO
+	END
+
+	EXECUTE (@sqlcmd)
+END;
 
 -- Waiter and Blocking Report
-SELECT 'Waiter_Blocking_Report' AS [Information],
-	-- blocked
-	es.session_id AS blocked_spid,
-	es.[status] AS [blocked_spid_status],
-	ot.task_state AS [blocked_task_status],
-	owt.wait_type AS blocked_spid_wait_type,
-	COALESCE(owt.wait_duration_ms, DATEDIFF(ms, es.last_request_start_time, GETDATE())) AS blocked_spid_wait_time_ms,
-	--er.total_elapsed_time AS blocked_elapsed_time_ms,
-	/* 
-		Check sys.dm_os_waiting_tasks for Exchange wait types in http://technet.microsoft.com/en-us/library/ms188743.aspx.
-		- Wait Resource e_waitPipeNewRow in CXPACKET waits – Producer waiting on consumer for a packet to fill.
-		- Wait Resource e_waitPipeGetRow in CXPACKET waits – Consumer waiting on producer to fill a packet.
-	*/
-	owt.resource_description AS blocked_spid_res_desc,
-	owt.[objid] AS blocked_objectid,
-	owt.pageid AS blocked_pageid,
-	CASE WHEN owt.pageid = 1 OR owt.pageid % 8088 = 0 THEN 'Is_PFS_Page'
-		WHEN owt.pageid = 2 OR owt.pageid % 511232 = 0 THEN 'Is_GAM_Page'
-		WHEN owt.pageid = 3 OR (owt.pageid - 1) % 511232 = 0 THEN 'Is_SGAM_Page'
-		WHEN owt.pageid IS NULL THEN NULL
-		ELSE 'Is_not_PFS_GAM_SGAM_page' END AS blocked_spid_res_type,
-	(SELECT qt.text AS [text()] 
-		FROM sys.dm_exec_sql_text(COALESCE(er.sql_handle, ec.most_recent_sql_handle)) AS qt 
-		FOR XML PATH(''), TYPE) AS [blocked_batch],
-	(SELECT SUBSTRING(qt2.text, 
-		1+(CASE WHEN er.statement_start_offset = 0 THEN 0 ELSE er.statement_start_offset/2 END),
-		1+(CASE WHEN er.statement_end_offset = -1 THEN DATALENGTH(qt2.text) ELSE er.statement_end_offset/2 END - (CASE WHEN er.statement_start_offset = 0 THEN 0 ELSE er.statement_start_offset/2 END))) AS [text()]
-		FROM sys.dm_exec_sql_text(COALESCE(er.sql_handle, ec.most_recent_sql_handle)) AS qt2 
-		FOR XML PATH(''), TYPE) AS [blocked_statement],
-	es.last_request_start_time AS blocked_last_start,
-	LEFT (CASE COALESCE(es.transaction_isolation_level, er.transaction_isolation_level)
-		WHEN 0 THEN '0-Unspecified' 
-		WHEN 1 THEN '1-ReadUncommitted(NOLOCK)' 
-		WHEN 2 THEN '2-ReadCommitted' 
-		WHEN 3 THEN '3-RepeatableRead' 
-		WHEN 4 THEN '4-Serializable' 
-		WHEN 5 THEN '5-Snapshot'
-		ELSE CONVERT (VARCHAR(30), COALESCE(es.transaction_isolation_level, er.transaction_isolation_level)) + '-UNKNOWN' 
-    END, 30) AS blocked_tran_isolation_level,
+IF @blocking = 1
+BEGIN
+	SELECT 'Waiter_Blocking_Report' AS [Information],
+		-- blocked
+		es.session_id AS blocked_spid,
+		es.[status] AS [blocked_spid_status],
+		ot.task_state AS [blocked_task_status],
+		owt.wait_type AS blocked_spid_wait_type,
+		COALESCE(owt.wait_duration_ms, DATEDIFF(ms, es.last_request_start_time, GETDATE())) AS blocked_spid_wait_time_ms,
+		--er.total_elapsed_time AS blocked_elapsed_time_ms,
+		/* 
+			Check sys.dm_os_waiting_tasks for Exchange wait types in http://technet.microsoft.com/en-us/library/ms188743.aspx.
+			- Wait Resource e_waitPipeNewRow in CXPACKET waits – Producer waiting on consumer for a packet to fill.
+			- Wait Resource e_waitPipeGetRow in CXPACKET waits – Consumer waiting on producer to fill a packet.
+		*/
+		owt.resource_description AS blocked_spid_res_desc,
+		owt.[objid] AS blocked_objectid,
+		owt.pageid AS blocked_pageid,
+		CASE WHEN owt.pageid = 1 OR owt.pageid % 8088 = 0 THEN 'Is_PFS_Page'
+			WHEN owt.pageid = 2 OR owt.pageid % 511232 = 0 THEN 'Is_GAM_Page'
+			WHEN owt.pageid = 3 OR (owt.pageid - 1) % 511232 = 0 THEN 'Is_SGAM_Page'
+			WHEN owt.pageid IS NULL THEN NULL
+			ELSE 'Is_not_PFS_GAM_SGAM_page' END AS blocked_spid_res_type,
+		(SELECT qt.text AS [text()] 
+			FROM sys.dm_exec_sql_text(COALESCE(er.sql_handle, ec.most_recent_sql_handle)) AS qt 
+			FOR XML PATH(''), TYPE) AS [blocked_batch],
+		(SELECT SUBSTRING(qt2.text, 
+			1+(CASE WHEN er.statement_start_offset = 0 THEN 0 ELSE er.statement_start_offset/2 END),
+			1+(CASE WHEN er.statement_end_offset = -1 THEN DATALENGTH(qt2.text) ELSE er.statement_end_offset/2 END - (CASE WHEN er.statement_start_offset = 0 THEN 0 ELSE er.statement_start_offset/2 END))) AS [text()]
+			FROM sys.dm_exec_sql_text(COALESCE(er.sql_handle, ec.most_recent_sql_handle)) AS qt2 
+			FOR XML PATH(''), TYPE) AS [blocked_statement],
+		es.last_request_start_time AS blocked_last_start,
+		LEFT (CASE COALESCE(es.transaction_isolation_level, er.transaction_isolation_level)
+			WHEN 0 THEN '0-Unspecified' 
+			WHEN 1 THEN '1-ReadUncommitted(NOLOCK)' 
+			WHEN 2 THEN '2-ReadCommitted' 
+			WHEN 3 THEN '3-RepeatableRead' 
+			WHEN 4 THEN '4-Serializable' 
+			WHEN 5 THEN '5-Snapshot'
+			ELSE CONVERT (VARCHAR(30), COALESCE(es.transaction_isolation_level, er.transaction_isolation_level)) + '-UNKNOWN' 
+		END, 30) AS blocked_tran_isolation_level,
 
-	-- blocker
-	er.blocking_session_id As blocker_spid,
-    CASE 
-        -- session has an active request, is blocked, but is blocking others or session is idle but has an open tran and is blocking others
-        WHEN (er2.session_id IS NULL OR owt.blocking_session_id IS NULL) AND (er.blocking_session_id = 0 OR er.session_id IS NULL) THEN 1
-        -- session is either not blocking someone, or is blocking someone but is blocked by another party
-        ELSE 0
-    END AS is_head_blocker,
-	(SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
-		qt2.text,
-		NCHAR(1),N'?'),NCHAR(2),N'?'),NCHAR(3),N'?'),NCHAR(4),N'?'),NCHAR(5),N'?'),NCHAR(6),N'?'),NCHAR(7),N'?'),NCHAR(8),N'?'),NCHAR(11),N'?'),NCHAR(12),N'?'),NCHAR(14),N'?'),NCHAR(15),N'?'),NCHAR(16),N'?'),NCHAR(17),N'?'),NCHAR(18),N'?'),NCHAR(19),N'?'),NCHAR(20),N'?'),NCHAR(21),N'?'),NCHAR(22),N'?'),NCHAR(23),N'?'),NCHAR(24),N'?'),NCHAR(25),N'?'),NCHAR(26),N'?'),NCHAR(27),N'?'),NCHAR(28),N'?'),NCHAR(29),N'?'),NCHAR(30),N'?'),NCHAR(31),N'?') 
-		AS [text()]
-		FROM sys.dm_exec_sql_text(COALESCE(er2.sql_handle, ec2.most_recent_sql_handle)) AS qt2 
-		FOR XML PATH(''), TYPE) AS [blocker_batch],
-	(SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
-		SUBSTRING(qt2.text, 
-		1+(CASE WHEN er2.statement_start_offset = 0 THEN 0 ELSE er2.statement_start_offset/2 END),
-		1+(CASE WHEN er2.statement_end_offset = -1 THEN DATALENGTH(qt2.text) ELSE er2.statement_end_offset/2 END - (CASE WHEN er2.statement_start_offset = 0 THEN 0 ELSE er2.statement_start_offset/2 END))),
-		NCHAR(1),N'?'),NCHAR(2),N'?'),NCHAR(3),N'?'),NCHAR(4),N'?'),NCHAR(5),N'?'),NCHAR(6),N'?'),NCHAR(7),N'?'),NCHAR(8),N'?'),NCHAR(11),N'?'),NCHAR(12),N'?'),NCHAR(14),N'?'),NCHAR(15),N'?'),NCHAR(16),N'?'),NCHAR(17),N'?'),NCHAR(18),N'?'),NCHAR(19),N'?'),NCHAR(20),N'?'),NCHAR(21),N'?'),NCHAR(22),N'?'),NCHAR(23),N'?'),NCHAR(24),N'?'),NCHAR(25),N'?'),NCHAR(26),N'?'),NCHAR(27),N'?'),NCHAR(28),N'?'),NCHAR(29),N'?'),NCHAR(30),N'?'),NCHAR(31),N'?') 
-		AS [text()]
-		FROM sys.dm_exec_sql_text(COALESCE(er2.sql_handle, ec2.most_recent_sql_handle)) AS qt2 
-		FOR XML PATH(''), TYPE) AS [blocker_statement],
-	es2.last_request_start_time AS blocker_last_start,
-	LEFT (CASE COALESCE(er2.transaction_isolation_level, es.transaction_isolation_level)
-		WHEN 0 THEN '0-Unspecified' 
-		WHEN 1 THEN '1-ReadUncommitted(NOLOCK)' 
-		WHEN 2 THEN '2-ReadCommitted' 
-		WHEN 3 THEN '3-RepeatableRead' 
-		WHEN 4 THEN '4-Serializable' 
-		WHEN 5 THEN '5-Snapshot' 
-		ELSE CONVERT (VARCHAR(30), COALESCE(er2.transaction_isolation_level, es.transaction_isolation_level)) + '-UNKNOWN' 
-    END, 30) AS blocker_tran_isolation_level,
+		-- blocker
+		er.blocking_session_id As blocker_spid,
+		CASE 
+			-- session has an active request, is blocked, but is blocking others or session is idle but has an open tran and is blocking others
+			WHEN (er2.session_id IS NULL OR owt.blocking_session_id IS NULL) AND (er.blocking_session_id = 0 OR er.session_id IS NULL) THEN 1
+			-- session is either not blocking someone, or is blocking someone but is blocked by another party
+			ELSE 0
+		END AS is_head_blocker,
+		(SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
+			qt2.text,
+			NCHAR(1),N'?'),NCHAR(2),N'?'),NCHAR(3),N'?'),NCHAR(4),N'?'),NCHAR(5),N'?'),NCHAR(6),N'?'),NCHAR(7),N'?'),NCHAR(8),N'?'),NCHAR(11),N'?'),NCHAR(12),N'?'),NCHAR(14),N'?'),NCHAR(15),N'?'),NCHAR(16),N'?'),NCHAR(17),N'?'),NCHAR(18),N'?'),NCHAR(19),N'?'),NCHAR(20),N'?'),NCHAR(21),N'?'),NCHAR(22),N'?'),NCHAR(23),N'?'),NCHAR(24),N'?'),NCHAR(25),N'?'),NCHAR(26),N'?'),NCHAR(27),N'?'),NCHAR(28),N'?'),NCHAR(29),N'?'),NCHAR(30),N'?'),NCHAR(31),N'?') 
+			AS [text()]
+			FROM sys.dm_exec_sql_text(COALESCE(er2.sql_handle, ec2.most_recent_sql_handle)) AS qt2 
+			FOR XML PATH(''), TYPE) AS [blocker_batch],
+		(SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
+			SUBSTRING(qt2.text, 
+			1+(CASE WHEN er2.statement_start_offset = 0 THEN 0 ELSE er2.statement_start_offset/2 END),
+			1+(CASE WHEN er2.statement_end_offset = -1 THEN DATALENGTH(qt2.text) ELSE er2.statement_end_offset/2 END - (CASE WHEN er2.statement_start_offset = 0 THEN 0 ELSE er2.statement_start_offset/2 END))),
+			NCHAR(1),N'?'),NCHAR(2),N'?'),NCHAR(3),N'?'),NCHAR(4),N'?'),NCHAR(5),N'?'),NCHAR(6),N'?'),NCHAR(7),N'?'),NCHAR(8),N'?'),NCHAR(11),N'?'),NCHAR(12),N'?'),NCHAR(14),N'?'),NCHAR(15),N'?'),NCHAR(16),N'?'),NCHAR(17),N'?'),NCHAR(18),N'?'),NCHAR(19),N'?'),NCHAR(20),N'?'),NCHAR(21),N'?'),NCHAR(22),N'?'),NCHAR(23),N'?'),NCHAR(24),N'?'),NCHAR(25),N'?'),NCHAR(26),N'?'),NCHAR(27),N'?'),NCHAR(28),N'?'),NCHAR(29),N'?'),NCHAR(30),N'?'),NCHAR(31),N'?') 
+			AS [text()]
+			FROM sys.dm_exec_sql_text(COALESCE(er2.sql_handle, ec2.most_recent_sql_handle)) AS qt2 
+			FOR XML PATH(''), TYPE) AS [blocker_statement],
+		es2.last_request_start_time AS blocker_last_start,
+		LEFT (CASE COALESCE(er2.transaction_isolation_level, es.transaction_isolation_level)
+			WHEN 0 THEN '0-Unspecified' 
+			WHEN 1 THEN '1-ReadUncommitted(NOLOCK)' 
+			WHEN 2 THEN '2-ReadCommitted' 
+			WHEN 3 THEN '3-RepeatableRead' 
+			WHEN 4 THEN '4-Serializable' 
+			WHEN 5 THEN '5-Snapshot' 
+			ELSE CONVERT (VARCHAR(30), COALESCE(er2.transaction_isolation_level, es.transaction_isolation_level)) + '-UNKNOWN' 
+		END, 30) AS blocker_tran_isolation_level,
 
-	-- blocked - other data
-	DB_NAME(er.database_id) AS blocked_database, 
-	es.[host_name] AS blocked_host,
-	es.[program_name] AS blocked_program, 
-	es.login_name AS blocked_login,
-	CASE WHEN es.session_id = -2 THEN 'Orphaned_distributed_tran' 
-		WHEN es.session_id = -3 THEN 'Defered_recovery_tran' 
-		WHEN es.session_id = -4 THEN 'Unknown_tran' ELSE NULL END AS blocked_session_comment,
-	es.is_user_process AS [blocked_is_user_process],
+		-- blocked - other data
+		DB_NAME(er.database_id) AS blocked_database, 
+		es.[host_name] AS blocked_host,
+		es.[program_name] AS blocked_program, 
+		es.login_name AS blocked_login,
+		CASE WHEN es.session_id = -2 THEN 'Orphaned_distributed_tran' 
+			WHEN es.session_id = -3 THEN 'Defered_recovery_tran' 
+			WHEN es.session_id = -4 THEN 'Unknown_tran' ELSE NULL END AS blocked_session_comment,
+		es.is_user_process AS [blocked_is_user_process],
 
-	-- blocker - other data
-	DB_NAME(er2.database_id) AS blocker_database,
-	es2.[host_name] AS blocker_host,
-	es2.[program_name] AS blocker_program,	
-	es2.login_name AS blocker_login,
-	CASE WHEN es2.session_id = -2 THEN 'Orphaned_distributed_tran' 
-		WHEN es2.session_id = -3 THEN 'Defered_recovery_tran' 
-		WHEN es2.session_id = -4 THEN 'Unknown_tran' ELSE NULL END AS blocker_session_comment,
-	es2.is_user_process AS [blocker_is_user_process]
-FROM sys.dm_exec_sessions (NOLOCK) es
-LEFT OUTER JOIN sys.dm_exec_requests (NOLOCK) er ON es.session_id = er.session_id
-LEFT OUTER JOIN sys.dm_exec_connections (NOLOCK) ec ON es.session_id = ec.session_id
-LEFT OUTER JOIN sys.dm_os_tasks (NOLOCK) ot ON er.session_id = ot.session_id AND er.request_id = ot.request_id
-LEFT OUTER JOIN sys.dm_exec_sessions (NOLOCK) es2 ON er.blocking_session_id = es2.session_id
-LEFT OUTER JOIN sys.dm_exec_requests (NOLOCK) er2 ON es2.session_id = er2.session_id
-LEFT OUTER JOIN sys.dm_exec_connections (NOLOCK) ec2 ON es2.session_id = ec2.session_id
-LEFT OUTER JOIN 
-(
-    -- In some cases (e.g. parallel queries, also waiting for a worker), one thread can be flagged as 
-    -- waiting for several different threads.  This will cause that thread to show up in multiple rows 
-    -- in our grid, which we don't want.  Use ROW_NUMBER to select the longest wait for each thread, 
-    -- and use it as representative of the other wait relationships this thread is involved in. 
-    SELECT waiting_task_address, session_id, exec_context_id, wait_duration_ms, 
-		wait_type, resource_address, blocking_task_address, blocking_session_id, 
-		blocking_exec_context_id, resource_description,
-		CASE WHEN [wait_type] LIKE 'PAGE%' AND [resource_description] LIKE '%:%' THEN CAST(RIGHT([resource_description], LEN([resource_description]) - CHARINDEX(':', [resource_description], LEN([resource_description])-CHARINDEX(':', REVERSE([resource_description])))) AS int)
-			WHEN [wait_type] LIKE 'LCK%' AND [resource_description] LIKE '%pageid%' AND ISNUMERIC(RIGHT(LEFT([resource_description],CHARINDEX('dbid=', [resource_description], CHARINDEX('pageid=', [resource_description])+6)-1),CHARINDEX('=',REVERSE(RTRIM(LEFT([resource_description],CHARINDEX('dbid=', [resource_description], CHARINDEX('pageid=', [resource_description])+6)-1)))))) = 1 THEN CAST(RIGHT(LEFT([resource_description],CHARINDEX('dbid=', [resource_description], CHARINDEX('pageid=', [resource_description])+6)-1),CHARINDEX('=',REVERSE(RTRIM(LEFT([resource_description],CHARINDEX('dbid=', [resource_description], CHARINDEX('pageid=', [resource_description])+6)-1))))) AS bigint)
-			ELSE NULL END AS pageid,
-		CASE WHEN [wait_type] LIKE 'LCK%' AND [resource_description] LIKE '%associatedObjectId%' AND ISNUMERIC(RIGHT([resource_description],CHARINDEX('=', REVERSE([resource_description]))-1)) = 1 THEN CAST(RIGHT([resource_description],CHARINDEX('=', REVERSE([resource_description]))-1) AS bigint)
-			ELSE NULL END AS [objid],
-		ROW_NUMBER() OVER (PARTITION BY waiting_task_address ORDER BY wait_duration_ms DESC) AS row_num
-    FROM sys.dm_os_waiting_tasks (NOLOCK)
-) owt ON ot.task_address = owt.waiting_task_address AND owt.row_num = 1
---OUTER APPLY sys.dm_exec_sql_text(er.sql_handle) est
---OUTER APPLY sys.dm_exec_query_plan(er.plan_handle) eqp
-WHERE es.session_id <> @@SPID AND es.is_user_process = 1 
-	--AND ((owt.wait_duration_ms/1000 > 5) OR (er.total_elapsed_time/1000) > 5 OR er.total_elapsed_time IS NULL) --Only report blocks > 5 Seconds plus head blocker
-	AND (es.session_id IN (SELECT er3.blocking_session_id FROM sys.dm_exec_requests (NOLOCK) er3) OR er.blocking_session_id IS NOT NULL OR er.blocking_session_id > 0)
-ORDER BY blocked_spid, is_head_blocker DESC, blocked_spid_wait_time_ms DESC, blocker_spid
+		-- blocker - other data
+		DB_NAME(er2.database_id) AS blocker_database,
+		es2.[host_name] AS blocker_host,
+		es2.[program_name] AS blocker_program,	
+		es2.login_name AS blocker_login,
+		CASE WHEN es2.session_id = -2 THEN 'Orphaned_distributed_tran' 
+			WHEN es2.session_id = -3 THEN 'Defered_recovery_tran' 
+			WHEN es2.session_id = -4 THEN 'Unknown_tran' ELSE NULL END AS blocker_session_comment,
+		es2.is_user_process AS [blocker_is_user_process]
+	FROM sys.dm_exec_sessions (NOLOCK) es
+	LEFT OUTER JOIN sys.dm_exec_requests (NOLOCK) er ON es.session_id = er.session_id
+	LEFT OUTER JOIN sys.dm_exec_connections (NOLOCK) ec ON es.session_id = ec.session_id
+	LEFT OUTER JOIN sys.dm_os_tasks (NOLOCK) ot ON er.session_id = ot.session_id AND er.request_id = ot.request_id
+	LEFT OUTER JOIN sys.dm_exec_sessions (NOLOCK) es2 ON er.blocking_session_id = es2.session_id
+	LEFT OUTER JOIN sys.dm_exec_requests (NOLOCK) er2 ON es2.session_id = er2.session_id
+	LEFT OUTER JOIN sys.dm_exec_connections (NOLOCK) ec2 ON es2.session_id = ec2.session_id
+	LEFT OUTER JOIN 
+	(
+		-- In some cases (e.g. parallel queries, also waiting for a worker), one thread can be flagged as 
+		-- waiting for several different threads.  This will cause that thread to show up in multiple rows 
+		-- in our grid, which we don't want.  Use ROW_NUMBER to select the longest wait for each thread, 
+		-- and use it as representative of the other wait relationships this thread is involved in. 
+		SELECT waiting_task_address, session_id, exec_context_id, wait_duration_ms, 
+			wait_type, resource_address, blocking_task_address, blocking_session_id, 
+			blocking_exec_context_id, resource_description,
+			CASE WHEN [wait_type] LIKE 'PAGE%' AND [resource_description] LIKE '%:%' THEN CAST(RIGHT([resource_description], LEN([resource_description]) - CHARINDEX(':', [resource_description], LEN([resource_description])-CHARINDEX(':', REVERSE([resource_description])))) AS int)
+				WHEN [wait_type] LIKE 'LCK%' AND [resource_description] LIKE '%pageid%' AND ISNUMERIC(RIGHT(LEFT([resource_description],CHARINDEX('dbid=', [resource_description], CHARINDEX('pageid=', [resource_description])+6)-1),CHARINDEX('=',REVERSE(RTRIM(LEFT([resource_description],CHARINDEX('dbid=', [resource_description], CHARINDEX('pageid=', [resource_description])+6)-1)))))) = 1 THEN CAST(RIGHT(LEFT([resource_description],CHARINDEX('dbid=', [resource_description], CHARINDEX('pageid=', [resource_description])+6)-1),CHARINDEX('=',REVERSE(RTRIM(LEFT([resource_description],CHARINDEX('dbid=', [resource_description], CHARINDEX('pageid=', [resource_description])+6)-1))))) AS bigint)
+				ELSE NULL END AS pageid,
+			CASE WHEN [wait_type] LIKE 'LCK%' AND [resource_description] LIKE '%associatedObjectId%' AND ISNUMERIC(RIGHT([resource_description],CHARINDEX('=', REVERSE([resource_description]))-1)) = 1 THEN CAST(RIGHT([resource_description],CHARINDEX('=', REVERSE([resource_description]))-1) AS bigint)
+				ELSE NULL END AS [objid],
+			ROW_NUMBER() OVER (PARTITION BY waiting_task_address ORDER BY wait_duration_ms DESC) AS row_num
+		FROM sys.dm_os_waiting_tasks (NOLOCK)
+	) owt ON ot.task_address = owt.waiting_task_address AND owt.row_num = 1
+	--OUTER APPLY sys.dm_exec_sql_text(er.sql_handle) est
+	--OUTER APPLY sys.dm_exec_query_plan(er.plan_handle) eqp
+	WHERE es.session_id <> @@SPID AND es.is_user_process = 1 
+		--AND ((owt.wait_duration_ms/1000 > 5) OR (er.total_elapsed_time/1000) > 5 OR er.total_elapsed_time IS NULL) --Only report blocks > 5 Seconds plus head blocker
+		AND (es.session_id IN (SELECT er3.blocking_session_id FROM sys.dm_exec_requests (NOLOCK) er3) OR er.blocking_session_id IS NOT NULL OR er.blocking_session_id > 0)
+	ORDER BY blocked_spid, is_head_blocker DESC, blocked_spid_wait_time_ms DESC, blocker_spid
+END;
 
-/*
 -- Stored procedure stats
-DECLARE @sqlmajorver int, @sqlcmd VARCHAR(4000)
-SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) & 0xff);
-
-IF @sqlmajorver >= 11
-BEGIN
+IF @spstats = 1 AND @sqlmajorver >= 11
+BEGIN 
 	SET @sqlcmd = N'SELECT CASE WHEN ps.database_id = 32767 THEN ''ResourceDB'' ELSE DB_NAME(ps.database_id) END AS DatabaseName, 
 	CASE WHEN ps.database_id = 32767 THEN NULL ELSE OBJECT_NAME(ps.[object_id], ps.database_id) END AS ObjectName,
 	type_desc,
@@ -535,11 +518,11 @@ BEGIN
  FROM sys.dm_exec_procedure_stats (NOLOCK) ps
  CROSS APPLY sys.dm_exec_query_plan(ps.plan_handle) qp'
 	EXEC (@sqlcmd);
- END
+END;
  
 -- Query stats
-IF @sqlmajorver >= 11
-BEGIN
+IF @qrystats = 1 AND @sqlmajorver >= 11
+BEGIN 
 	SET @sqlcmd = N'SELECT CASE WHEN CONVERT(int,pa.value) = 32767 THEN ''ResourceDB'' ELSE DB_NAME(CONVERT(int,pa.value)) END AS DatabaseName,
 	(SELECT st.text AS [text()] FROM sys.dm_exec_sql_text(qs.plan_handle) AS st FOR XML PATH(''''), TYPE) AS [sqltext],
 	qs.creation_time AS cached_time,
@@ -560,10 +543,10 @@ FROM sys.dm_exec_query_stats (NOLOCK) AS qs
 CROSS APPLY sys.dm_exec_plan_attributes(qs.plan_handle) AS pa
 WHERE pa.attribute = ''dbid'''
 	EXEC (@sqlcmd);
-END
+END;
 
 -- Trigger stats
-IF @sqlmajorver >= 11
+IF @trstats = 1 AND @sqlmajorver >= 11
 BEGIN
 	SET @sqlcmd = N'SELECT CASE WHEN ts.database_id = 32767 THEN ''ResourceDB'' ELSE DB_NAME(ts.database_id) END AS DatabaseName, 
 	CASE WHEN ts.database_id = 32767 THEN NULL ELSE OBJECT_NAME(ts.[object_id], ts.database_id) END AS ObjectName,
@@ -587,13 +570,13 @@ BEGIN
 	ts.last_physical_reads, ts.min_physical_reads, ts.max_physical_reads,
 	ts.total_logical_writes/ts.execution_count AS avg_logical_writes,
 	ts.last_logical_writes, ts.min_logical_writes, ts.max_logical_writes
- FROM sys.dm_exec_trigger_stats (NOLOCK) ts
- CROSS APPLY sys.dm_exec_query_plan(ts.plan_handle) qp'
+FROM sys.dm_exec_trigger_stats (NOLOCK) ts
+CROSS APPLY sys.dm_exec_query_plan(ts.plan_handle) qp'
 	EXEC (@sqlcmd);
-END
+END;
 
 -- Function stats
-IF @sqlmajorver >= 11
+IF @fnstats = 1 AND @sqlmajorver >= 11
 BEGIN
 	SET @sqlcmd = N'SELECT CASE WHEN fs.database_id = 32767 THEN ''ResourceDB'' ELSE DB_NAME(fs.database_id) END AS DatabaseName, 
 	CASE WHEN fs.database_id = 32767 THEN NULL ELSE OBJECT_NAME(fs.[object_id], fs.database_id) END AS ObjectName,
@@ -617,15 +600,7 @@ BEGIN
 	fs.last_physical_reads, fs.min_physical_reads, fs.max_physical_reads,
 	fs.total_logical_writes/fs.execution_count AS avg_logical_writes,
 	fs.last_logical_writes, fs.min_logical_writes, fs.max_logical_writes
- FROM sys.dm_exec_function_stats (NOLOCK) fs
- CROSS APPLY sys.dm_exec_query_plan(fs.plan_handle) qp'
+FROM sys.dm_exec_function_stats (NOLOCK) fs
+CROSS APPLY sys.dm_exec_query_plan(fs.plan_handle) qp'
 	EXEC (@sqlcmd);
-END
-*/
-
-/*
--- Acquired locks
-SELECT tl.*, sp.[object_id], sp.index_id 
-FROM sys.dm_tran_locks (NOLOCK) tl
-LEFT JOIN sys.partitions (NOLOCK) sp ON tl.resource_associated_entity_id = sp.[hobt_id]
-*/
+END;

+ 0 - 0
Running-Blocked-Processes/Running-Blocked-Processes.ipynb → usp_WhatsUp/whatsup_diagnostic_queries.ipynb