如果作业中的任何步骤失败,请通知操作员

时间:2010-10-04 19:35:15

标签: sql-server notifications database-administration sql-server-agent server-administration

我是否可以(如何)配置Sql Server 2008以通知操作员作业中的任何步骤是否失败?

我有一个Sql Server作业,其中有几个步骤来更新来自多个不同来源的数据,然后是最后一步,对数据执行多次计算。所有“数据刷新”步骤都设置为“失败时转到下一步”。一般来说,如果其中一个数据刷新失败,我仍然希望最后一步运行,但我仍然希望收到关于中间故障的通知,所以如果它们一直失败,我可以进行调查。

8 个答案:

答案 0 :(得分:24)

以下是我们的工作方式。我们用这个

添加最后一个T-SQL步骤(通常称为“检查步骤”)
SELECT  step_name, message
FROM    msdb.dbo.sysjobhistory
WHERE   instance_id > COALESCE((SELECT MAX(instance_id) FROM msdb.dbo.sysjobhistory
                                WHERE job_id = $(ESCAPE_SQUOTE(JOBID)) AND step_id = 0), 0)
        AND job_id = $(ESCAPE_SQUOTE(JOBID))
        AND run_status <> 1 -- success

IF      @@ROWCOUNT <> 0
        RAISERROR('Ooops', 16, 1)

请注意,此代码使用tokens in job steps$(...)部分),因此代码无法在SSMS中执行。它基本上试图在sysjobhistory中查找当前作业的先前步骤的条目,并查找失败状态。

在“属性” - >“高级”中,您还可以检查包含历史记录中的步骤输出以从步骤失败中获取消息。将 On failure action 保留为退出作业报告失败

答案 1 :(得分:3)

@wqw接受的答案非常好。

我已将其扩展为那些启用了数据库邮件的人,可以通过电子邮件发送有关确切失败的内容和方式的详细信息。此外,还将icvader的答案纳入此页面,以考虑重试。

对于我们这些需要更多细节来判断是否需要在非现场/待命时采取紧急行动的人来说,真的很有帮助。

DECLARE 

@YourRecipients as varchar(1000) = 'myadminemail@bloatcorp.com'
,@YourMailProfileName as varchar(255) = 'Database Mail'

,@Msg as varchar(1000)
,@NumofFails as smallint
,@JobName as varchar(1000)
,@Subj as varchar(1000)
,@i as smallint = 1


---------------Fetch List of Step Errors------------
SELECT *
INTO #Errs

FROM

    (
    SELECT 
      rank() over (PARTITION BY step_id ORDER BY step_id) rn
    , ROW_NUMBER() over (partition by step_id order by run_date desc, run_time desc) ReverseTryOrder
    ,j.name job_name
    ,run_status
    , step_id
    , step_name
    , [message]

    FROM    msdb.dbo.sysjobhistory h
    join msdb.dbo.sysjobs j on j.job_id = h.job_id

    WHERE   instance_id > COALESCE((SELECT MAX(instance_id) FROM msdb.dbo.sysjobhistory
                                    WHERE job_id = $(ESCAPE_SQUOTE(JOBID)) AND step_id = 0), 0)
            AND h.job_id = $(ESCAPE_SQUOTE(JOBID))
    ) as agg

WHERE ReverseTryOrder = 1 ---Pick the last retry attempt of each step
  AND run_status <> 1 -- show only those that didn't succeed 


SET @NumofFails = ISNULL(@@ROWCOUNT,0)---Stored here because we'll still need the rowcount after it's reset.


-------------------------If there are any failures assemble email and send ------------------------------------------------
IF  @NumofFails <> 0
    BEGIN

        DECLARE @PluralS as char(1) = CASE WHEN @NumofFails > 1 THEN 's' ELSE '' END ---To make it look like a computer knows English
        SELECT top 1 @Subj = 'Job: ' + job_name + ' had ' + CAST(@NumofFails as varchar(3)) + ' step' + @PluralS + ' that failed'
                    ,@Msg =  'The trouble is... ' +CHAR(13) + CHAR(10)+CHAR(13) + CHAR(10)

                        FROM dbo.#Errs


        WHILE @i <= @NumofFails 
        BEGIN
            SELECT @Msg = @Msg + 'Step:' + CAST(step_id as varchar(3)) + ': ' + step_name  +CHAR(13) + CHAR(10)

            + [message] +CHAR(13) + CHAR(10)+CHAR(13) + CHAR(10) FROM dbo.#Errs
            WHERE rn = @i


            SET @i = @i + 1
        END

            exec msdb.dbo.sp_send_dbmail
            @recipients = @YourRecipients,
            @subject = @Subj,
            @profile_name = @YourMailProfileName,
            @body = @Msg


    END

与其基于的其他答案有一点不同:不会将整个工作视为错误。 这是为了在Aborted和Completed with Errors之间保留作业历史中的区别。

答案 2 :(得分:2)

对上述答案的改进,以防有人想使用sql server agent中的运算符发送电子邮件;并使用存储在msdb中的数据库配置文件名称:

cd projects\myapp
ruby script\server

答案 3 :(得分:1)

我的大部分步骤都设置为重试,因为一个独特的translog场景导致偶尔阻塞。即使步骤已成功重试,wqw的帖子也会发出警报。我做了一个改编,如果一个步骤失败就不会发出警报,但是在重试时是成功的。

SELECT  step_id, MIN(run_status)
FROM    msdb.dbo.sysjobhistory
WHERE   instance_id > COALESCE((SELECT MAX(instance_id) FROM msdb.dbo.sysjobhistory
                                WHERE job_id = $(ESCAPE_SQUOTE(JOBID)) AND step_id = 0), 0)
        AND job_id = $(ESCAPE_SQUOTE(JOBID))
GROUP BY step_id
HAVING MIN(run_status) <> 1 -- success

IF @@ROWCOUNT <> 0
RAISERROR('FailedStep', 16, 1)

答案 4 :(得分:1)

坚定的答案是完美的解决方案(谢谢):完美无瑕地工作..小编辑。正如wqw之前所述,在SSMS中不起作用,将其作为最后一步添加并运行该作业。

WHERE instance_id > COALESCE
(
(
SELECT MAX(instance_id) 
FROM msdb.dbo.sysjobhistory
WHERE job_id = '2XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX' AND step_id = 0), 0
)
AND h.job_id = '2XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX'
) 
as agg

答案 5 :(得分:0)

转到“作业属性”&gt; “通知”标签&gt;作业完成时要执行的操作

下方检查电子邮件复选框,然后从下拉列表中选择“当作业失败时”并保存作业。

阅读http://msdn.microsoft.com/en-us/library/ms191130.aspx

上的第4点

如果您想通过电子邮件通知运营商,请选中电子邮件,从列表中选择一个运营商,然后选择以下选项之一:

  • 当作业成功时:在作业成功完成时通知操作员。

  • 当作业失败时:在作业完成失败时通知操作员。

  • 作业完成时:无论完成状态如何都通知操作员。

答案 6 :(得分:0)

在每个步骤中添加代码:

if @@error > 0
EXEC sp_send_dbmail @profile_name='DBATeam',
@recipients=dbadmin@somewhere.com',
@subject='SomeJob SomeStep failed',
@body='This is the body of SomeJob SomeStep failed' 

答案 7 :(得分:0)

我也有这个问题,但是在不同的情况下:我的许多SQL作业都是由第三方工具(实际上是ERP)创建的,在该工具中我无权添加最后一步或任何其他细节。 / p>

因此,我正在寻找一种方法来告诉SQL Server任何失败的作业,而无需手动编辑每个新作业。

有什么主意吗?

顺便说一句,我尝试了故障安全操作员,但它似乎无法通知失败的作业。