Vous pouvez créer un travail qui vérifie la table msdb.dbo.sysjobhistory toutes les minutes (ou à la fréquence souhaitée). Vous souhaiterez peut-être implémenter une table de files d'attente afin de n'envoyer le message pour une seule défaillance d'instance qu'une seule fois.
USE msdb;
GO
CREATE TABLE dbo.ReportServerJob_FailQueue
(
job_id UNIQUEIDENTIFIER,
run_date INT,
run_time INT, -- horrible schema, just matching sysjobhistory
sql_message_id INT,
sent BIT NOT NULL DEFAULT 0,
PRIMARY KEY (job_id, run_date, run_time)
);
Ainsi, votre code, que vous pouvez planifier dans un travail, devient:
INSERT dbo.ReportServerJob_FailQueue
(job_id, run_date, run_time, sql_message_id)
SELECT job_id, run_date, run_time, sql_message_id
FROM msdb.dbo.sysjobhistory AS h
WHERE step_id = 0
AND run_status = 0
AND EXISTS
(
SELECT 1 FROM msdb.dbo.sysjobs AS j
INNER JOIN msdb.dbo.syscategories AS c
ON j.category_id = c.category_id
WHERE j.job_id = h.job_id
AND c.name = 'Report Server'
)
AND NOT EXISTS
(
SELECT 1 FROM dbo.ReportServerJob_FailQueue
WHERE job_id = h.job_id
AND run_date = h.run_date
AND run_time = h.run_time
);
Maintenant, je suppose que vous voulez envoyer un e-mail individuel pour chaque échec, donc cela pourrait également faire partie du travail (ou faire partie d'un travail différent, bien que ce ne soit pas nécessairement judicieux):
DECLARE
@subject NVARCHAR(4000),
@body NVARCHAR(4000),
@name SYSNAME,
@id UNIQUEIDENTIFIER,
@date INT,
@time INT,
@msg INT;
DECLARE c CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR SELECT q.job_id, q.run_date, q.run_time, q.sql_message_id, j.name
FROM dbo.ReportServerJob_FailQueue AS q
INNER JOIN msdb.dbo.sysjobs AS j
ON q.job_id = j.job_id
WHERE q.sent = 0;
OPEN c;
FETCH NEXT FROM c INTO @id, @date, @time, @msg, @name;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @subject = 'Report Server job ' + @name + ' failed.';
SET @body = 'Error number: ' + RTRIM(@msg);
BEGIN TRY
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'default', -- you may need to change this
@recipients = 'foo@bar.com', -- you will need to change this
@subject = @subject,
@body = @body;
UPDATE dbo.ReportServerJob_FailQueue
SET sent = 1
WHERE job_id = @id
AND run_date = @date
AND run_time = @time;
END TRY
BEGIN CATCH
PRINT 'Will have to try that one again later.';
END
FETCH NEXT FROM c INTO @id, @date, @time, @msg, @name;
END
CLOSE c; DEALLOCATE c;
Il existe également d'autres options:
- tirer dans sysjobhistory.message
- regarder les étapes individuelles qui ont échoué
- n'envoyez un message pour n'importe quel travail qu'une fois en n minutes / heures même s'il y a plusieurs échecs
- envoyer un seul e-mail avec une liste de toutes les tâches qui ont échoué, au lieu d'un e-mail pour chaque échec
- vous voudrez peut-être inclure les run_date et run_time dans le message, car l'e-mail peut ne pas être envoyé ou reçu assez rapidement pour être une mesure précise du moment où le travail a réellement échoué (je ne l'ai pas inclus ici car leurs choix de type de données horribles faire un formatage qui remplit un PITA royal)
- vous voudrez probablement nettoyer les anciennes lignes après un certain temps, donc une commande de purge peut également être souhaitée
Si la messagerie de base de données n'est pas déjà configurée, consultez ce didacticiel .
Vous pouvez également utiliser des outils tiers (par exemple, SQL Sentry Event Manager ) qui simplifieront la tâche. Divulgation complète: je travaille pour SQL Sentry.
AND EXISTS
partie entière duINSERT/SELECT
. Et probablement changer le nomReportServerJob_FailQueue
en quelque chose de plus générique. :-)