คุณสามารถสร้างงานที่ตรวจสอบตาราง msdb.dbo.sysjobhistory ทุกนาที (หรือบ่อยครั้งที่คุณต้องการ) คุณอาจต้องการใช้ตารางคิวเพื่อให้คุณส่งข้อความสำหรับความล้มเหลวของอินสแตนซ์เดียวเพียงครั้งเดียวเท่านั้น
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)
);
ดังนั้นรหัสของคุณที่คุณสามารถกำหนดเวลาในงานได้กลายเป็น:
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
);
ตอนนี้ฉันคิดว่าคุณต้องการส่งอีเมลแยกต่างหากสำหรับแต่ละความล้มเหลวดังนั้นนี่อาจเป็นส่วนหนึ่งของงานได้เช่นกัน (หรือเป็นส่วนหนึ่งของงานที่แตกต่างกัน
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;
มีตัวเลือกอื่น ๆ ด้วย:
- ดึงใน sysjobhistory.message
- ดูทีละขั้นตอนที่ล้มเหลว
- ส่งข้อความสำหรับงานใด ๆ เพียงครั้งเดียวใน n นาที / ชั่วโมงแม้ว่าจะมีหลายความล้มเหลว
- ส่งอีเมลเดียวพร้อมรายการของงานทั้งหมดที่ล้มเหลวแทนอีเมลสำหรับแต่ละความล้มเหลว
- คุณอาจต้องการรวม run_date และ run_time ในข้อความเนื่องจากอีเมลอาจไม่สามารถส่งหรือรับได้อย่างรวดเร็วเพียงพอที่จะเป็นการวัดที่แม่นยำเมื่องานล้มเหลวจริง ๆ (ฉันไม่ได้รวมไว้ที่นี่เพราะตัวเลือกประเภทข้อมูลที่น่ากลัวของพวกเขา ทำให้การจัดรูปแบบเป็นสิ่งที่ PITA)
- คุณอาจต้องการล้างแถวเก่าหลังจากผ่านไปสักพักดังนั้นอาจต้องการคำสั่งล้างข้อมูลเช่นกัน
หากยังไม่มีการตั้งค่าเมลฐานข้อมูลโปรดดูบทช่วยสอนนี้
คุณสามารถใช้เครื่องมือของบุคคลที่สาม (เช่นSQL Sentry Event Manager ) ซึ่งจะทำให้ง่ายขึ้นมาก การเปิดเผยแบบเต็ม: ฉันทำงานให้กับ SQL Sentry
AND EXISTS
INSERT/SELECT
และอาจเปลี่ยนชื่อเป็นชื่อReportServerJob_FailQueue
สามัญมากกว่านี้ :-)