Notifica operatore Se un passaggio in processo non viene
Domanda
Can I (Come fare) configurare SQL Server 2008 per notificare un operatore se qualsiasi fase del lavoro viene a mancare?
Ho un processo di SQL Server con diversi passaggi per aggiornare i dati provenienti da più fonti diverse, seguiti da una fase finale che esegue diversi calcoli sui dati. Tutte le "Aggiornamento dati" passaggi sono impostati su "Vai alla fase successiva in caso di errore". In generale, se uno dei rinfresca dati non riesce, voglio ancora il passo finale di corsa, ma ho ancora voglia di essere avvisato sui fallimenti intermedi, quindi se non riescono positiv, posso indagare.
Soluzione
Ecco come lo facciamo. Aggiungiamo un passo dell'ultimo T-SQL (di solito chiamati "passaggi di controllo") con questo
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)
Si noti che questo codice sta usando token nei passaggi di lavoro (la $(...)
parte), quindi codice non possono essere eseguite in SSMS come sono. Si cerca fondamentalmente per trovare le voci di precedenti fasi del lavoro corrente in sysjobhistory
e cerca gli stati di errore.
In Properties-> Avanzate è anche possibile controllare Includi uscita passo nella storia per ottenere il messaggio dal fallimento passo. Lasciare il In azione fallimento per Esci il mancato rapporto di lavoro .
Altri suggerimenti
@wqw 's risposta accettata è eccellente.
ho esteso per coloro che hanno Posta elettronica database abilitato alla posta elettronica un po 'più in dettaglio su ciò che non è riuscito e come. incorpora anche la risposta di icvader in questa pagina, per tener conto di tentativi.
Dovrebbe essere molto utile per quelli di noi che hanno bisogno di maggiore dettaglio per giudicare se sia necessaria un'azione urgente quando fuori sede / a chiamata.
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
Una differenza dalle altre risposte su cui ha basato la sua: non solleva tutto il lavoro come un errore. Quella di mantenere la distinzione nella cronologia dei lavori tra l'annullate e completata con errori.
Un miglioramento alla risposta di cui sopra, nel caso in cui qualcuno vuole utilizzare gli operatori di agente di SQL Server per inviare e-mail; e utilizzare il nome del profilo del database memorizzato in 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
Ho la maggior parte dei miei passi impostati per riprovare a causa di uno scenario translog unico che provoca il blocco occasionale. Il post di wqw avviserà anche se un passo è riprovato con successo. Ho fatto un adattamento che non sarà avviso se un passo è fallito, ma poi è stato un successo sul tentativo.
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 risposta di Adamantish è la soluzione perfetta (Grazie): funzionato senza problemi .. modifiche minori. Come wqw detto prima, non funziona in SQL Server Management Studio, aggiungere questo come ultimo passo ed eseguire il lavoro.
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
Vai alla Proprietà del lavoro> scheda Notifica> azione da eseguire quando il lavoro è stato completato
sotto controllo che la casella di controllo e-mail e selezionare "Quando il lavoro viene a mancare" dal menu a discesa e salvare il lavoro.
Leggi punto 4 sulla http://msdn.microsoft.com/en- us / library / ms191130.aspx
Se si desidera informare un operatore via e-mail, controllare la posta elettronica, selezionare un operatore dall'elenco, quindi selezionare una delle seguenti:
-
Quando il lavoro riesce:. Per avvisare l'operatore quando il completamento del lavoro con successo
-
Quando il lavoro non viene:. Per avvisare l'operatore quando il completamento del lavoro senza successo
-
Quando il completamento del lavoro:. Per segnalare all'operatore indipendentemente dallo status di completamento
in ogni codice passaggio aggiuntivo:
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'