@@ -3020,7 +3020,12 @@ BEGIN
30203020 sort_order =
30213021 ROW_NUMBER () OVER (ORDER BY COUNT_BIG (DISTINCT b .transaction_id ) DESC )
30223022 FROM #blocks AS b
3023- WHERE (b .database_name = @database_name
3023+ /* Genuine lock contention only. Non-lock and self-referential reports are
3024+ counted separately in check_id 10; IS NULL keeps unknown-type rows here
3025+ so nothing is silently dropped. */
3026+ WHERE (b .resource_owner_type = N ' LOCK'
3027+ OR b .resource_owner_type IS NULL )
3028+ AND (b .database_name = @database_name
30243029 OR @database_name IS NULL )
30253030 AND (b .contentious_object = @object_name
30263031 OR @object_name IS NULL )
@@ -3067,7 +3072,12 @@ BEGIN
30673072 sort_order =
30683073 ROW_NUMBER () OVER (ORDER BY COUNT_BIG (DISTINCT b .transaction_id ) DESC )
30693074 FROM #blocks AS b
3070- WHERE (b .database_name = @database_name
3075+ /* Genuine lock contention only. Non-lock and self-referential reports are
3076+ counted separately in check_id 10; IS NULL keeps unknown-type rows here
3077+ so nothing is silently dropped. */
3078+ WHERE (b .resource_owner_type = N ' LOCK'
3079+ OR b .resource_owner_type IS NULL )
3080+ AND (b .database_name = @database_name
30713081 OR @database_name IS NULL )
30723082 AND (b .contentious_object = @object_name
30733083 OR @object_name IS NULL )
@@ -4096,6 +4106,63 @@ BEGIN
40964106 )
40974107 OPTION (RECOMPILE );
40984108
4109+ IF @debug = 1
4110+ BEGIN
4111+ RAISERROR (' Inserting #block_findings, check_id 10' , 0 , 1 ) WITH NOWAIT ;
4112+ END ;
4113+
4114+ /*
4115+ Non-lock and self-referential blocked process reports.
4116+
4117+ The blocked process monitor fires for any task that waits longer than
4118+ the configured blocked process threshold, not only lock waits. So a long
4119+ memory grant (RESOURCE_SEMAPHORE), parallelism (CXPACKET/exchange), or
4120+ other non-lock wait surfaces as a blocked process report, frequently with
4121+ the blocked and blocking process being the same session (a session
4122+ "blocking itself"). These carry a real signal but are not lock contention,
4123+ so they would otherwise be miscounted alongside genuine lock blocking in
4124+ the findings above. resource_owner_type is LOCK only for real lock waits;
4125+ every other value (GENERIC, EXCHANGE, THREAD, etc.) is a non-lock wait.
4126+ */
4127+ INSERT
4128+ #block_findings
4129+ (
4130+ check_id,
4131+ database_name ,
4132+ object_name ,
4133+ finding_group,
4134+ finding,
4135+ sort_order
4136+ )
4137+ SELECT
4138+ check_id =
4139+ 10 ,
4140+ database_name =
4141+ ISNULL (b .database_name , N ' unknown' ),
4142+ object_name =
4143+ N ' -' ,
4144+ finding_group =
4145+ N ' Non-Lock and Self Blocking' ,
4146+ finding =
4147+ N ' The database ' +
4148+ ISNULL (b .database_name , N ' unknown' ) +
4149+ N ' has had ' +
4150+ CONVERT (nvarchar (20 ), COUNT_BIG (DISTINCT b .event_time )) +
4151+ N ' blocked process report(s) for non-lock waits such as memory grants, parallelism, or other non-lock resources. ' +
4152+ N ' The blocked process monitor fires for any task that waits longer than the configured blocked process threshold, not only lock waits, ' +
4153+ N ' so these frequently show a session blocking itself and do not indicate lock contention.' ,
4154+ sort_order =
4155+ ROW_NUMBER () OVER (ORDER BY COUNT_BIG (DISTINCT b .event_time ) DESC )
4156+ FROM #blocks AS b
4157+ WHERE b .resource_owner_type <> N ' LOCK'
4158+ AND (b .database_name = @database_name
4159+ OR @database_name IS NULL )
4160+ AND (b .contentious_object = @object_name
4161+ OR @object_name IS NULL )
4162+ GROUP BY
4163+ b .database_name
4164+ OPTION (RECOMPILE );
4165+
40994166 IF @debug = 1
41004167 BEGIN
41014168 RAISERROR (' Inserting #block_findings, check_id 1000' , 0 , 1 ) WITH NOWAIT ;
0 commit comments