作业类别中的任何作业失败时发出警报


11

是否可以在SQL Server 2008中设置警报,以便在特定类别的作业失败时将发送电子邮件?

我想知道是因为我想在SSRS订阅失败时设置一封电子邮件,并且所有这些订阅都是Report Server类别中的作业。

编辑 -事实证明,当SSRS订阅失败时,作业本身不会失败,因此我的问题将不适用于SSRS订阅监视。但是我仍然想知道我们在环境中运行的其他工作


步骤至少会失败吗?我在下面的回答着眼于“报表服务器”类别中的作业,但是如果您只想要所有作业,则可以删除的整个AND EXISTS部分INSERT/SELECT。并且可能将名称更改为ReportServerJob_FailQueue更通用的名称。:-)
亚伦·伯特兰

不幸的是,没有任何步骤失败-但我相信我可以提出其他一些监视机制!
JHFB 2012年

Answers:


10

您可以创建一个每分钟检查一次msdb.dbo.sysjobhistory表的作业(或根据需要进行一次检查)。您可能想要实现一个队列表,因此对于任何单个实例故障,您一次只能发送一次消息。

USE msdb;
GO

CREATE TABLE dbo.ReportServerJob_FailQueue
(
  job_id UNIQUEIDENTIFIER,
  run_date INT,
  run_time INT, -- horrible schema, just matching sysjobhistory
  sql_message_id INT,
  sent BIT NOT NULL DEFAULT 0,
  PRIMARY KEY (job_id, run_date, run_time)
);

因此,您可以在工作中安排的代码将变为:

INSERT dbo.ReportServerJob_FailQueue
  (job_id, run_date, run_time, sql_message_id)
SELECT job_id, run_date, run_time, sql_message_id
FROM msdb.dbo.sysjobhistory AS h
WHERE step_id = 0 
AND run_status = 0
AND EXISTS 
(
  SELECT 1 FROM msdb.dbo.sysjobs AS j
    INNER JOIN msdb.dbo.syscategories AS c
    ON j.category_id = c.category_id
    WHERE j.job_id = h.job_id
   AND c.name = 'Report Server'
)
AND NOT EXISTS 
(
  SELECT 1 FROM dbo.ReportServerJob_FailQueue
    WHERE job_id = h.job_id
    AND run_date = h.run_date
    AND run_time = h.run_time
);

现在,我假设您想为每次失败发送一封单独​​的电子邮件,因此这也可能是工作的一部分(或者是其他工作的一部分,尽管不一定明智):

DECLARE 
  @subject NVARCHAR(4000),
  @body NVARCHAR(4000),
  @name SYSNAME,
  @id UNIQUEIDENTIFIER,
  @date INT,
  @time INT,
  @msg INT;

DECLARE c CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR SELECT q.job_id, q.run_date, q.run_time, q.sql_message_id, j.name
  FROM dbo.ReportServerJob_FailQueue AS q
  INNER JOIN msdb.dbo.sysjobs AS j
  ON q.job_id = j.job_id
  WHERE q.sent = 0;

OPEN c;

FETCH NEXT FROM c INTO @id, @date, @time, @msg, @name;

WHILE @@FETCH_STATUS = 0
BEGIN

  SET @subject = 'Report Server job ' + @name + ' failed.';
  SET @body = 'Error number: ' + RTRIM(@msg);

  BEGIN TRY
    EXEC msdb.dbo.sp_send_dbmail 
      @profile_name = 'default',     -- you may need to change this
      @recipients   = 'foo@bar.com', -- you will need to change this
      @subject      = @subject,
      @body         = @body;

    UPDATE dbo.ReportServerJob_FailQueue
      SET sent = 1 
      WHERE job_id = @id
      AND run_date = @date
      AND run_time = @time;
  END TRY
  BEGIN CATCH
    PRINT 'Will have to try that one again later.';
  END

  FETCH NEXT FROM c INTO @id, @date, @time, @msg, @name;
END

CLOSE c; DEALLOCATE c;

还有其他一些选择:

  • 拉入sysjobhistory.message
  • 查看失败的各个步骤
  • 即使有多个失败,也仅在n分钟/小时内为任何作业发送一次消息
  • 发送一封包含所有失败作业列表的电子邮件,而不是每次失败的电子邮件
  • 您可能希望在消息中包含run_date和run_time,因为电子邮件发送或接收的速度可能不够快,无法准确地衡量作业实际何时失败(我在此处未添加电子邮件,因为他们选择了糟糕的数据类型将格式设置为皇家PITA)
  • 您可能需要在一段时间后清理旧行,因此也可能需要使用清除命令

如果尚未设置数据库邮件,请参阅本教程

您也可以使用第三方工具(例如SQL Sentry Event Manager),这将使很多事情变得更加简单。全面披露:我为SQL Sentry工作。


0

根据您的编辑,这仅是Aaron关于SSRS订阅失败本身(不仅仅是SQL Agent作业)的答案的扩展。我建议只是在工作监视工作中增加一个步骤,否则您可以将其作为一个单独的工作来完成。

要获取订阅状态,您只需检查ReportServer.dbo.ExecutionLog3 视图。该Status列将显示除rsSuccess故障以外的任何内容。只需过滤RequestType = 'Subscription'。您将需要进行一些时间检查,因此您不必每次都检查所有记录。如果您每15分钟运行一次作业,则只需检查TimeStart过去15分钟即可。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.