Уведомлять оператора, если ЛЮБОЙ шаг в выполнении задания
Могу ли я (как мне настроить Sql Server 2008 уведомлять оператора, если какой-либо шаг в работе сработал?
У меня есть задание сервера Sql с несколькими шагами для обновления данных из нескольких разных источников, за которым следует один последний шаг, который выполняет несколько вычислений по данным. Все шаги "обновления данных" установлены на "Перейти к следующему шагу при сбое". Вообще говоря, если одно из сбоев данных не удается, я все равно хочу, чтобы последний шаг выполнялся, но я все еще хочу получать уведомления о промежуточных ошибках, поэтому, если они терпят неудачу, я могу исследовать.
Ответы
Ответ 1
Вот как мы это делаем. Мы добавляем один последний шаг 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
и ищет статусы отказа.
В свойствах- > Дополнительно вы также можете проверить вывод шага Include в истории, чтобы получить сообщение об ошибке с шага. Оставьте действие "Вкл. Отказ", чтобы выйти из отказа отчета о работе.
Ответ 2
@wqw принят ответ отлично.
Я расширил его для тех, у кого есть Mail Mail, для отправки по электронной почте немного более подробной информации о том, что не удалось и как. Также включает ответ icvader на этой странице, чтобы учитывать повторы.
Должно быть очень полезно для тех из нас, кто нуждается в более подробных подробностях, чтобы судить о необходимости принятия срочных мер, если вы находитесь за пределами площадки/по вызову.
DECLARE
@YourRecipients as varchar(1000) = '[email protected]'
,@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 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.
Ответ 3
Перейдите в раздел "Свойства работы" > вкладка "Уведомление" > действие, выполняемое при завершении задания
при этом установите флажок "Электронная почта" и выберите "Когда сбой задания" в раскрывающемся списке и сохраните задание.
Прочитайте 4-й пункт в http://msdn.microsoft.com/en-us/library/ms191130.aspx
Если вы хотите уведомить оператора по электронной почте, отметьте E-mail, выберите оператора из списка и выберите одно из следующего:
-
Когда задание удастся: уведомить оператора о завершении задания.
-
При неудачном выполнении задания: уведомить оператора о неудачном завершении задания.
-
Когда задание завершается: для уведомления оператора независимо от состояния завершения.
Ответ 4
У меня есть большинство моих шагов для повторной попытки из-за уникального сценария трансляции, который вызывает случайную блокировку. Сообщение 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)
Ответ 5
Адамантистский ответ - идеальное решение (спасибо): работал безупречно.. мелкие изменения. Как указано выше, 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
Ответ 6
Улучшение приведенного выше ответа, если кто-то хочет использовать операторов в агенте sql server для отправки электронной почты; и используйте имя профиля базы данных, хранящееся в 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 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
Ответ 7
на каждом шаге добавьте код:
if @@error > 0
EXEC sp_send_dbmail @profile_name='DBATeam',
@[email protected]',
@subject='SomeJob SomeStep failed',
@body='This is the body of SomeJob SomeStep failed'