MantasTumenas / Zabbix-template-for-Microsoft-SQL-Server

Zabbix templates for Microsoft SQL Server. Features MS SQL performance counters. MS SQL instance Low Level Discovery. MS SQL database Low Level Discovery. MS SQL agent job Low Level Discovery. MS SQL database mirroring monitoring. MS SQL Always On monitoring. MS SQL Log Shipping monitoring. Supported versions Tested on Microsoft SQL Server 2012, 2014 and 2016. It may work with earlier versions, but some items (with missing performance counters) may be unsupported. For the extensive overview on the performance counters difference between MS SQL 2008 and MS SQL 2012 you can read here (https://blog.dbi-services.com/sql-server-2012-new-perfmon-counters/). Tested on Zabbix 3.4.0. It may work with earlier versions, but some items (for example service.info[service,]) may be unsupported. The template was started on Zabbix 2.4.0 but after each new Zabbix version, objects were modified or new things were added.
GNU General Public License v3.0
49 stars 27 forks source link

Processes Blocked >1 over 300 sec period show what query? #40

Closed killmasta93 closed 2 years ago

killmasta93 commented 2 years ago

Hi, Would it be possible that when it get blocked to show which query is doing the blocking and the user that is blocking it?

maybe something like this?

WITH [Blocking]
AS (SELECT w.[session_id]
   ,s.[original_login_name]
   ,s.[login_name]
   ,w.[wait_duration_ms]
   ,w.[wait_type]
   ,r.[status]
   ,r.[wait_resource]
   ,w.[resource_description]
   ,s.[program_name]
   ,w.[blocking_session_id]
   ,s.[host_name]
   ,r.[command]
   ,r.[percent_complete]
   ,r.[cpu_time]
   ,r.[total_elapsed_time]
   ,r.[reads]
   ,r.[writes]
   ,r.[logical_reads]
   ,r.[row_count]
   ,q.[text]
   ,q.[dbid]
   ,p.[query_plan]
   ,r.[plan_handle]
 FROM [sys].[dm_os_waiting_tasks] w
 INNER JOIN [sys].[dm_exec_sessions] s ON w.[session_id] = s.[session_id]
 INNER JOIN [sys].[dm_exec_requests] r ON s.[session_id] = r.[session_id]
 CROSS APPLY [sys].[dm_exec_sql_text](r.[plan_handle]) q
 CROSS APPLY [sys].[dm_exec_query_plan](r.[plan_handle]) p
 WHERE w.[session_id] > 50
  AND w.[wait_type] NOT IN ('DBMIRROR_DBM_EVENT'
      ,'ASYNC_NETWORK_IO'))
SELECT b.[session_id] AS [WaitingSessionID]
      ,b.[blocking_session_id] AS [BlockingSessionID]
      ,b.[login_name] AS [WaitingUserSessionLogin]
      ,s1.[login_name] AS [BlockingUserSessionLogin]
      ,b.[original_login_name] AS [WaitingUserConnectionLogin] 
      ,s1.[original_login_name] AS [BlockingSessionConnectionLogin]
      ,b.[wait_duration_ms] AS [WaitDuration]
      ,b.[wait_type] AS [WaitType]
      ,t.[request_mode] AS [WaitRequestMode]
      ,UPPER(b.[status]) AS [WaitingProcessStatus]
      ,UPPER(s1.[status]) AS [BlockingSessionStatus]
      ,b.[wait_resource] AS [WaitResource]
      ,t.[resource_type] AS [WaitResourceType]
      ,t.[resource_database_id] AS [WaitResourceDatabaseID]
      ,DB_NAME(t.[resource_database_id]) AS [WaitResourceDatabaseName]
      ,b.[resource_description] AS [WaitResourceDescription]
      ,b.[program_name] AS [WaitingSessionProgramName]
      ,s1.[program_name] AS [BlockingSessionProgramName]
      ,b.[host_name] AS [WaitingHost]
      ,s1.[host_name] AS [BlockingHost]
      ,b.[command] AS [WaitingCommandType]
      ,b.[text] AS [WaitingCommandText]
      ,b.[row_count] AS [WaitingCommandRowCount]
      ,b.[percent_complete] AS [WaitingCommandPercentComplete]
      ,b.[cpu_time] AS [WaitingCommandCPUTime]
      ,b.[total_elapsed_time] AS [WaitingCommandTotalElapsedTime]
      ,b.[reads] AS [WaitingCommandReads]
      ,b.[writes] AS [WaitingCommandWrites]
      ,b.[logical_reads] AS [WaitingCommandLogicalReads]
      ,b.[query_plan] AS [WaitingCommandQueryPlan]
      ,b.[plan_handle] AS [WaitingCommandPlanHandle]
FROM [Blocking] b
INNER JOIN [sys].[dm_exec_sessions] s1
ON b.[blocking_session_id] = s1.[session_id]
INNER JOIN [sys].[dm_tran_locks] t
ON t.[request_session_id] = b.[session_id]
WHERE t.[request_status] = 'WAIT'
GO
MantasTumenas commented 2 years ago

Short answer - no, not possible.

MantasTumenas commented 2 years ago

Longer explanation. You want for a Zabbix to retrieve the blocking user (User name? Login name? SPID? AppName? HostName?) and the query which is a head blocker (?). So you want to receive two values into one field. Now, how big is a blocking query? I mean, how many symbols, characters, (n)varchars it will span? 100? 200? 500? 1000? Zabbix manual shows me that if you select Type of information Text (long text data), text data limits will be 255 characters. Best case scenario - you will get the beginning of the blocking query, worst case scenario - item will become unsupported. Lets say, you managed to get the info you needed into zabbix - what would be your course of action after receiving alert about blocking? You would still need to log into SQL server, kill that blocking query, right? My suggestions. 1. Use zabbix blocking alert to get alerts. 2. User https://www.brentozar.com/archive/2014/03/extended-events-doesnt-hard/ to capture blocking alerts, to log them and to have a possibility to analyze them. Good luck