Sie können einen Job erstellen, der jede Minute (oder wie oft Sie möchten) die Tabelle msdb.dbo.sysjobhistory überprüft. Möglicherweise möchten Sie eine Warteschlangentabelle implementieren, damit Sie die Nachricht für einen einzelnen Instanzfehler immer nur einmal senden.
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)
);
Ihr Code, den Sie in einem Job planen können, lautet dann:
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
);
Nun gehe ich davon aus, dass Sie für jeden Fehler eine individuelle E-Mail senden möchten, sodass dies auch Teil des Jobs sein kann (oder Teil eines anderen Jobs, obwohl dies nicht unbedingt sinnvoll ist):
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;
Es gibt auch einige andere Optionen:
- Ziehen Sie sysjobhistory.message ein
- Schauen Sie sich einzelne Schritte an, die fehlgeschlagen sind
- Senden Sie eine Nachricht für einen Auftrag nur einmal in n Minuten / Stunden, selbst wenn mehrere Fehler vorliegen
- Senden Sie eine einzelne E-Mail mit einer Liste aller fehlgeschlagenen Jobs anstelle einer E-Mail für jeden Fehler
- Möglicherweise möchten Sie run_date und run_time in die Nachricht aufnehmen, da die E-Mail möglicherweise nicht schnell genug gesendet oder empfangen wird, um genau zu messen, wann der Auftrag tatsächlich fehlgeschlagen ist (ich habe sie hier nicht aufgenommen, weil sie schreckliche Datentypen ausgewählt haben Formatierung dieses Materials zu einer königlichen PITA machen)
- Möglicherweise möchten Sie alte Zeilen nach einiger Zeit bereinigen, daher ist möglicherweise auch ein Bereinigungsbefehl erwünscht
Wenn Database Mail noch nicht eingerichtet ist, lesen Sie bitte dieses Tutorial .
Sie können auch Tools von Drittanbietern (z. B. SQL Sentry Event Manager ) verwenden, die dies erheblich vereinfachen. Vollständige Offenlegung: Ich arbeite für SQL Sentry.
AND EXISTS
Teil des Jobs entfernenINSERT/SELECT
. Und wahrscheinlich den NamenReportServerJob_FailQueue
in etwas allgemeineres ändern . :-)