Sql server 如果作业中的任何步骤失败,通知操作员
我可以如何配置Sql Server 2008,以便在作业中的任何步骤失败时通知操作员Sql server 如果作业中的任何步骤失败,通知操作员,sql-server,notifications,database-administration,sql-server-agent,server-administration,Sql Server,Notifications,Database Administration,Sql Server Agent,Server Administration,我可以如何配置Sql Server 2008,以便在作业中的任何步骤失败时通知操作员 我有一个Sql Server作业,其中包括几个步骤来更新来自多个不同来源的数据,然后是最后一个步骤,该步骤对数据执行多个计算。所有数据刷新步骤都设置为在出现故障时转到下一步。一般来说,如果其中一个数据刷新失败,我仍然希望运行最后一步,但我仍然希望得到有关中间故障的通知,因此如果它们持续失败,我可以进行调查。转到作业属性>通知选项卡>作业完成时要执行的操作 在该选项下,选中电子邮件复选框,并从下拉列表中选择作业失
我有一个Sql Server作业,其中包括几个步骤来更新来自多个不同来源的数据,然后是最后一个步骤,该步骤对数据执行多个计算。所有数据刷新步骤都设置为在出现故障时转到下一步。一般来说,如果其中一个数据刷新失败,我仍然希望运行最后一步,但我仍然希望得到有关中间故障的通知,因此如果它们持续失败,我可以进行调查。转到作业属性>通知选项卡>作业完成时要执行的操作 在该选项下,选中电子邮件复选框,并从下拉列表中选择作业失败时,然后保存作业 阅读上面的第四点 如果要通过电子邮件通知操作员,请选中电子邮件,从列表中选择操作员,然后选择以下选项之一: 作业成功时:作业成功完成时通知操作员 作业失败时:作业未成功完成时通知操作员 作业完成时:通知操作员,无论完成状态如何
下面是我们如何做到这一点。我们添加了最后一个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)
请注意,此代码正在使用$。。。部分,因此代码不能按原样在SSMS中执行。它基本上尝试在sysjobhistory中查找当前作业的前几个步骤的条目,并查找故障状态
在Properties->Advanced中,您还可以选中Include step output In history(在历史记录中包含步骤输出),以从步骤失败中获取消息。保留On failure操作以退出作业报告失败。在每个步骤中添加代码:
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'
我的大多数步骤都设置为重试,因为一个独特的translog场景会导致偶尔的阻塞。即使已成功重试步骤,wqw的post也会发出警报。我做了一个调整,如果某个步骤失败,它将不会发出警报,但重试成功
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)
@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
与其他答案的一个不同之处在于:不会将整个工作视为一个错误。
这是为了在工作历史中保留中止和错误完成之间的区别。Adamantish的答案是完美的解决方案谢谢:工作完美无瑕。。小编辑。正如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
对上述答案的改进,以防有人想使用SQLServer代理中的运算符发送电子邮件;并使用存储在msdb中的数据库配置文件名称:
DECLARE @EmailRecipients as varchar(1000)
DECLARE @MailProfileName as varchar(255)
DECLARE @Msg as varchar(1000)
DECLARE @NumofFails as smallint
DECLARE @JobName as varchar(1000)
DECLARE @Subj as varchar(1000)
DECLARE @i as smallint = 1
SELECT @EmailRecipients = email_address
FROM msdb.dbo.sysoperators
WHERE name = <Operator Name>
SELECT TOP(1) @MailProfileName = name
FROM msdb.dbo.sysmail_profile
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 @NumofFails <> 0
BEGIN
DECLARE @PluralS as char(1) = CASE WHEN @NumofFails > 1 THEN 's' ELSE '' END
SELECT top 1 @Subj = job_name + ':'+ CAST(@NumofFails as varchar(3)) + '''Check Steps'' Report',
@Msg = '''Check Steps'' has reported that one or more Steps failed during execution of ' + job_name + 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 = @EmailRecipients,
@subject = @Subj,
@profile_name = @MailProfileName,
@body = @Msg
END
不幸的是,这并不能解决问题。首先,这将在完成后发送电子邮件,无论成功与否。我希望只有在一个步骤失败时才能看到电子邮件此外,完成电子邮件不包含任何指示单个步骤失败的文本。它只是简单地说明工作成功了。我如何知道某个特定步骤失败。当作业未成功完成时,如果作业未通知操作员,请使用此选项。这意味着您将收到通知,如果作业以任何失败步骤完成,则即使任何步骤失败,也将完成作业,因为为作业步骤指定了“错误转到下一步”。然后,您可以查看工作历史以了解更多详细信息。。你说什么!作业失败时的选项不会发送电子邮件,因为最后一步成功,即退出作业报告成功,非常漂亮和巧妙。我把它扩展成了一个不那么漂亮但很有用的东西;看我的答案。我还没有仔细看这个问题,但我要说一件事。它的样式比我当时编写SQL的方式要好得多。