Уведомить оператора, если ЛЮБОЙ шаг в работе не удался
Могу ли я (как мне) настроить Sql Server 2008 для уведомления оператора, если какой-либо шаг в Задании не выполняется?
У меня есть задание Sql Server с несколькими шагами для обновления данных из нескольких разных источников, после чего следует один последний шаг, который выполняет несколько вычислений над данными. Все шаги "обновления данных" установлены на "Перейти к следующему шагу при ошибке". Вообще говоря, если одно из обновлений данных завершается неудачно, я все же хочу, чтобы последний шаг был выполнен, но я все еще хочу получать уведомления о промежуточных сбоях, поэтому, если они не проходят постоянно, я могу провести расследование.
7 ответов
Вот как мы это делаем. Мы добавим один последний шаг 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
и ищет статусы отказа.
В Свойства-> Дополнительно вы также можете установить флажок Включить вывод шага в историю, чтобы получить сообщение об ошибке шага. Оставьте действие При сбое, чтобы выйти из отчета о сбое задания.
Принятый ответ @wqw превосходен.
Я продлил это для тех, у кого включена функция Database Mail, чтобы отправлять по электронной почте немного больше информации о том, что именно не удалось и как. Также содержит ответ 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
Одно отличие от других ответов, на которых оно основано: не поднимает всю работу как ошибку. Это позволит сохранить различие в истории заданий между прерванными и завершенными ошибками.
Улучшение в ответе выше, в случае, если кто-то хочет использовать операторы в агенте сервера SQL для отправки электронной почты; и использовать имя профиля базы данных, хранящееся в 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
Большинство моих шагов настроено на повторную попытку из-за уникального сценария транслога, который иногда вызывает блокировку. Сообщение 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)
Ответ Адамантиша - идеальное решение (спасибо): сработало безупречно... незначительные правки. Как указано ранее в 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
У меня тоже есть этот вопрос, но в другом контексте: многие из моих SQL-заданий создаются сторонним инструментом (на самом деле ERP), в котором я не могу добавить последний шаг или какие-либо другие особенности.
Итак, я ищу способ сообщить SQL Server, чтобы он уведомлял меня о ЛЮБОМ неудачном задании, без необходимости вручную редактировать каждое новое задание.
Любая идея?
Кстати, я пробовал Fail-Safe Operator, но, похоже, он не может уведомлять о неудачных заданиях.
На каждом шаге добавьте код:
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'
Перейдите в Свойства задания> вкладка Уведомление> действие, которое нужно выполнить после завершения задания.
под этим установите флажок "Электронная почта" и выберите "В случае сбоя задания" из выпадающего списка и сохраните задание.
Прочитайте 4-й пункт на http://msdn.microsoft.com/en-us/library/ms191130.aspx
Если вы хотите уведомить оператора по электронной почте, проверьте адрес электронной почты, выберите оператора из списка, а затем выберите один из следующих вариантов:
Когда задание выполнено успешно: уведомить оператора об успешном завершении задания.
Если задание не выполнено: уведомить оператора о неудачном завершении задания.
Когда задание завершено: уведомить оператора независимо от статуса завершения.