Notifier l'opérateur en cas d'échec toute étape dans l'emploi
Question
Can I (Comment puis-je) configure Sql Server 2008 pour notifier un opérateur si une étape du travail échoue?
I ai un travail SQL Server avec plusieurs étapes de mise à jour des données provenant de multiples sources différentes, suivie par une étape finale qui effectue plusieurs calculs sur les données. Toutes les « actualisation des données » étapes sont à « Passez à l'étape suivante en cas d'échec ». D'une manière générale, si l'une des données rafraîchi échoue, je veux encore la dernière étape à courir, mais je veux encore être informé au sujet des pannes intermédiaires, donc si elles ne parviennent pas consistantly, je peux enquêter.
La solution
Voici comment nous le faisons. Nous ajoutons une dernière étape T-SQL (communément appelées « étapes de contrôle ») avec cette
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)
Notez que ce code utilise dans les étapes d'emploi (la partie $(...)
), de sorte que le code ne peut être exécuté dans SSMS comme il est. Il essaie basiquement de trouver les entrées des étapes précédentes de la tâche en cours dans sysjobhistory
et recherche des statuts d'échec.
Dans Propriétés-> Avancé, vous pouvez également vérifier Inclure la sortie de l'étape dans l'histoire pour obtenir le message de l'échec de l'étape. Laissez le sur l'action d'échec Quitter l'échec de rapports d'emploi .
Autres conseils
@wqw « s réponse acceptée est excellente.
Je l'ai étendu pour ceux qui ont permis de messagerie de base par courriel un peu plus de détails sur exactement ce qui a échoué et comment. Intègre également la réponse de icvader sur cette page pour tenir compte de réitérations.
devrait être très utile pour ceux d'entre nous qui ont besoin de plus de détails pour juger si une action urgente est nécessaire lorsque hors site / sur appel.
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
Une différence des autres réponses sur lesquelles sa base: ne soulève pas tout le travail comme une erreur. C'est de conserver la distinction dans l'histoire de l'emploi entre Aborted et terminée avec des erreurs.
Une amélioration de la réponse ci-dessus, cas où quelqu'un veut utiliser les opérateurs agent serveur SQL pour envoyer un courriel; et utiliser le nom du profil de base de données stockées dans 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
J'ai la plupart de mes pas mis à nouvelle tentative en raison d'un scénario translogarithmique unique qui provoque le blocage occasionnel. Le poste de wqw alertera même si une étape a avec succès une nouvelle tentative. J'ai fait une adaptation qui ne sera pas alerte si une étape a échoué, mais a été un succès sur nouvelle tentative.
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)
La réponse de Adamantish est la solution parfaite (Merci): a parfaitement fonctionné .. modifications mineures. Comme indiqué précédemment wqw, ne fonctionnera pas dans SSMS, ajoutez une dernière étape et exécuter la tâche.
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
Aller à Propriétés d'emploi> onglet Notification> action à effectuer lorsque le travail est terminé
sous le cocher la case E-mail et sélectionnez « Quand le travail échoue » dans le menu déroulant et enregistrer le travail.
Lire 4ème point http://msdn.microsoft.com/en- nous / bibliothèque / ms191130.aspx
Si vous souhaitez notifier un opérateur par e-mail, consultez E-mail, sélectionnez un opérateur dans la liste, puis sélectionnez l'une des options suivantes:
-
Quand le travail réussit. D'informer l'opérateur lorsque le travail est terminé avec succès
-
Quand le travail échoue. D'informer l'opérateur lorsque le travail est terminé sans succès
-
Quand le travail est terminé:. D'aviser l'opérateur quel que soit l'état d'achèvement
dans chaque code add étape:
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'