监视 SQL Server 阻止的进程

Lea*_*min 1 sql-server sp-whoisactive

我一直在使用sp_whoisactive,这对于查找运行会话和阻塞的详细信息非常有帮助。

我想检查是否有任何选项可以根据此过程安排作业,并仅在数据库上存在活动阻塞并且阻塞持续时间超过可配置的分钟数时才提醒我。

此外,只有当它达到超过可配置的数据库阻塞数量时才应触发警报。

我使用了http://www.sqlserver-dba.com/2017/01/how-to-monitor-blocked-processes-with-sql-alert-and-email-sp_whoisactive-report.html中给出的详细信息,但是它发送每次运行时发出警报,似乎没有检查是否有阻塞。无论是只运行一个查询还是运行多个查询,无论是阻塞还是不阻塞,都发送电子邮件。不确定,如果我错过了什么。用于阻塞的 SQL 作业

Bre*_*zar 6

您链接到的脚本使用 SQL Server 的内置阻止进程报告。它没有任何关于阻塞级别的配置选项——它只是在一个时间间隔(比如每 5 秒)唤醒,检查阻塞,如果找到,运行脚本。

有一个Blocked Process Threshold 设置,但这只是决定了 Blocked Process Report 运行的时间间隔——比如每 5 秒。(不要低于那个。)

如果您想构建自己的自定义阻塞进程报告并在其中放置有关发生阻塞的程度以及在哪些数据库中的逻辑,这将是留给读者的练习。您可以从Darko 的 Build a Custom Blocked Process Report 开始

根据我多年来的经验,我看到有人想要构建此类报告,然后他们做的下一件事就是构建 Outlook 规则,将所有这些警报移动到一个文件夹中,然后他们阅读它们之后。如果您打算这样做,请不要费心发送电子邮件。

只需设置一个扩展事件会话来查找被阻止的进程和死锁 - 请注意,您需要更改服务器的文件位置和名称:

CREATE EVENT SESSION [blocked_process] ON SERVER
ADD EVENT sqlserver.blocked_process_report(
    ACTION(sqlserver.client_app_name,
           sqlserver.client_hostname,
           sqlserver.database_name)) ,
ADD EVENT sqlserver.xml_deadlock_report (
    ACTION(sqlserver.client_app_name,
           sqlserver.client_hostname,
           sqlserver.database_name))
ADD TARGET package0.asynchronous_file_target
(SET filename = N'c:\temp\XEventSessions\blocked_process.xel',
     metadatafile = N'c:\temp\XEventSessions\blocked_process.xem',
     max_file_size=(65536),
     max_rollover_files=5)
WITH (MAX_DISPATCH_LATENCY = 5SECONDS)
GO
Run Code Online (Sandbox Code Playgroud)

启用 SQL Server 的阻塞进程报告:

EXEC sp_configure ‘show advanced options’, 1 ;
GO
RECONFIGURE ;
GO
/* Enabled the blocked process report */
EXEC sp_configure 'blocked process threshold', '5';
RECONFIGURE
GO
/* Start the Extended Events session */
ALTER EVENT SESSION [blocked_process] ON SERVER
STATE = START;
Run Code Online (Sandbox Code Playgroud)

当你想检查阻塞时,这个查询会读取文件:

WITH events_cte AS (
  SELECT
    xevents.event_data,
    DATEADD(mi,
    DATEDIFF(mi, GETUTCDATE(), CURRENT_TIMESTAMP),
    xevents.event_data.value(
      '(event/@timestamp)[1]', 'datetime2')) AS [event time] ,
    xevents.event_data.value(
      '(event/action[@name="client_app_name"]/value)[1]', 'nvarchar(128)')
      AS [client app name],
    xevents.event_data.value(
      '(event/action[@name="client_hostname"]/value)[1]', 'nvarchar(max)')
      AS [client host name],
    xevents.event_data.value(
      '(event[@name="blocked_process_report"]/data[@name="database_name"]/value)[1]', 'nvarchar(max)')
      AS [database name],
    xevents.event_data.value(
      '(event[@name="blocked_process_report"]/data[@name="database_id"]/value)[1]', 'int')
      AS [database_id],
    xevents.event_data.value(
      '(event[@name="blocked_process_report"]/data[@name="object_id"]/value)[1]', 'int')
      AS [object_id],
    xevents.event_data.value(
      '(event[@name="blocked_process_report"]/data[@name="index_id"]/value)[1]', 'int')
      AS [index_id],
    xevents.event_data.value(
      '(event[@name="blocked_process_report"]/data[@name="duration"]/value)[1]', 'bigint') / 1000
      AS [duration (ms)],
    xevents.event_data.value(
      '(event[@name="blocked_process_report"]/data[@name="lock_mode"]/text)[1]', 'varchar')
      AS [lock_mode],
    xevents.event_data.value(
      '(event[@name="blocked_process_report"]/data[@name="login_sid"]/value)[1]', 'int')
      AS [login_sid],
    xevents.event_data.query(
      '(event[@name="blocked_process_report"]/data[@name="blocked_process"]/value/blocked-process-report)[1]')
      AS blocked_process_report,
    xevents.event_data.query(
      '(event/data[@name="xml_report"]/value/deadlock)[1]')
      AS deadlock_graph
  FROM    sys.fn_xe_file_target_read_file
    ('C:\temp\XEventSessions\blocked_process*.xel',
     'C:\temp\XEventSessions\blocked_process*.xem',
     null, null)
    CROSS APPLY (SELECT CAST(event_data AS XML) AS event_data) as xevents
)
SELECT
  CASE WHEN blocked_process_report.value('(blocked-process-report[@monitorLoop])[1]', 'nvarchar(max)') IS NULL
       THEN 'Deadlock'
       ELSE 'Blocked Process'
       END AS ReportType,
  [event time],
  CASE [client app name] WHEN '' THEN ' -- N/A -- '
                         ELSE [client app name]
                         END AS [client app _name],
  CASE [client host name] WHEN '' THEN ' -- N/A -- '
                          ELSE [client host name]
                          END AS [client host name],
  [database name],
  COALESCE(OBJECT_SCHEMA_NAME(object_id, database_id), ' -- N/A -- ') AS [schema],
  COALESCE(OBJECT_NAME(object_id, database_id), ' -- N/A -- ') AS [table],
  index_id,
  [duration (ms)],
  lock_mode,
  COALESCE(SUSER_NAME(login_sid), ' -- N/A -- ') AS username,
  CASE WHEN blocked_process_report.value('(blocked-process-report[@monitorLoop])[1]', 'nvarchar(max)') IS NULL
       THEN deadlock_graph
       ELSE blocked_process_report
       END AS Report
FROM events_cte
ORDER BY [event time] DESC ;
Run Code Online (Sandbox Code Playgroud)

希望能帮助您入门。另外,仅供参考,我编辑了您的问题以删除有关 sp_WhoIsActive 是我的部分 - 不是。这是亚当·马卡尼克的。如果你亲自见到他,你应该向他表示感谢,并给他买他喜欢的饮料。