ฉันจะให้ SQL Server ส่งอีเมลรายละเอียดข้อผิดพลาดให้ฉันเมื่องานล้มเหลวได้อย่างไร


14

SQL Server ช่วยให้คุณกำหนดค่างานเพื่อส่งการแจ้งเตือนทางอีเมลเมื่อล้มเหลว นี่เป็นวิธีที่ง่ายและมีประสิทธิภาพในการตรวจสอบงานของคุณ อย่างไรก็ตามการแจ้งเตือนเหล่านี้จะไม่รวมถึงรายละเอียดใด ๆ - เพียงแค่แจ้งความสำเร็จหรือความล้มเหลว

หากงานล้มเหลวนี่คือลักษณะของอีเมลเตือนทั่วไป:

JOB RUN:        'DBA - Consistency Check Databases' was run on 8/14/2011 at 12:00:04 AM
DURATION:       0 hours, 0 minutes, 0 seconds
STATUS:         Failed
MESSAGES:       The job failed.  The Job was invoked by Schedule 2 (Nightly Before 
                Backup 12AM).  The last step to run was step 1 (Check Databases).

ในการระบุสาเหตุของความล้มเหลวคุณต้องไปยังอินสแตนซ์ใน Studio จัดการเซิร์ฟเวอร์ SQL ค้นหางานและดูประวัติการดำเนินการ ในสภาพแวดล้อมขนาดใหญ่อาจเป็นความเจ็บปวดที่ต้องทำอย่างต่อเนื่อง

อีเมลแจ้งเตือนที่สมบูรณ์แบบจะรวมถึงสาเหตุของความล้มเหลวล่วงหน้าและช่วยให้คุณทำงานได้ทันที

ฉันคุ้นเคยกับวิธีแก้ไขปัญหานี้ ใครบ้างมีประสบการณ์กับมันบ้าง ข้อเสียของมันคือ:

  1. คุณต้องเพิ่มขั้นตอนใหม่ทุกงานที่คุณมีและ
  2. คุณต้องภาวนาว่าไม่มีใครมายุ่งกับกระบวนการเตือนภัย spDBA_job_notification

มีใครคิดวิธีแก้ปัญหาที่ดีกว่าบ้างไหม?

คำตอบ:


10

บางสิ่งที่คุณอาจทำนั่นเป็นเพียงแค่ความคิดการทิ้งความคิด ...

สร้างงานเดียวที่ตรวจสอบตารางงานเป็นระยะ ๆ ใน msdb เพื่อดูว่างานใดแสดงว่าล้มเหลวซึ่งสามารถทำได้ด้วยแบบสอบถาม T-SQL ที่ดี จากนั้นคุณสามารถไปที่ตาราง sysjobsteps และดูว่ามีการตั้งค่าล็อกเอาต์พุตสำหรับงานหรือไม่ มีขั้นตอนการจัดเก็บส่งอีเมลแนบไฟล์ที่มัน คุณจะสามารถเห็นสิ่งที่งานทำตั้งแต่ต้นจนจบโดยไม่ต้องแตะเซิร์ฟเวอร์

จากนั้นอาจให้สคริปต์ PowerShell ตรวจสอบบันทึกเหตุการณ์เพื่อหาข้อผิดพลาด ช่วยให้คุณสามารถกรองบิตที่ดีมากที่จะได้รับสิ่งที่ประเภทข้อความที่คุณกำลังมองหา คุณสามารถตั้งค่าให้เป็นงานตัวแทน SQL เพื่อรันเป็นระยะ จากนั้นในสคริปต์ PowerShell ให้ใช้อีเมล cmdlet เพื่อส่งข้อความหากพบข้อความนั้น

แนวคิดที่ดึงมาไกลเกินไปที่นี่มีเพียงบางอย่างที่ฉันคิด


3

ผมมีประสบการณ์กับความคิดดังกล่าวข้างต้น เป็นเรื่องที่ดี แต่ความคิดที่ดีกว่าคือการทำสิ่งที่ Shawn พูด

สิ่งที่เราทำคือการสร้างงานที่ทำงานทุก 5 นาทีและสแกนตาราง MSDB เกี่ยวกับความล้มเหลวของงาน สำหรับแต่ละงานที่มีความล้มเหลวเราจะเรียกใช้ SP spDBA_job_notificationด้วย ID ของตัวเองดังนั้น SP จะสแกนขั้นตอนประวัติ MSDB เพื่อหาข้อผิดพลาดและส่งอีเมลทั้งหมด จากเอกสาร SP: "กระบวนงานที่เก็บไว้ใช้ ID งานเพื่อสอบถามตารางตัวแทน msdb สำหรับข้อความแสดงข้อผิดพลาดล่าสุดสำหรับงานนั้น"

ดังนั้นแทนที่จะแค่เปลี่ยนทุกงานควรสร้างงานเดียวที่ทำทุกอย่าง ;-)

อีกแนวคิดหนึ่งคือการตั้งค่างานทั้งหมดให้เขียนไปที่ Windows Event Viewer ในกรณีที่เกิดข้อผิดพลาด / ล้มเหลวและอ่านจากที่นั่นด้วยproc xp_ReadErrorLog ที่เพิ่มขึ้นหรือเครื่องมืออัตโนมัติหากคุณมีงานในเครือข่ายของคุณอยู่แล้ว ตัวอย่างเช่นเราใช้HPOVเพื่อตรวจสอบปัญหาของระบบและสามารถกำหนดค่าการแจ้งเตือนอย่างง่าย ๆ สำหรับข้อผิดพลาดของตัวแสดงเหตุการณ์ทั้งหมด (ไม่จำเป็นต้องมีงานที่กำหนดเองหรือขั้นตอนใด ๆ )


2

ลองสิ่งนี้และลองเสียบตัวแปรของคุณตามที่ต้องการใน TSQL กุญแจสำคัญในที่นี้คือการวางขั้นตอนนี้เป็นขั้นตอนสุดท้ายของแต่ละเอเจนต์ SQL แต่ละงาน แต่แต่ละขั้นตอนของงานด้านบนนั้นจำเป็นต้องไปที่ NEXT STEP ไม่ว่าจะเป็น FAILURE หรือ SUCCESS ... ทำงานให้ฉันได้ดีที่สุด แต่โปรด รายงานปัญหาใด ๆ ที่คุณพบ เราอยู่ใน SQL Server 2008 R2 ดังนั้นนี่คือที่ที่มันถูกใช้ในที่ที่ฉันตั้งค่าไว้ในปัจจุบัน

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
BEGIN
        RAISERROR('*** SQL Agent Job Prior Step Failure Occurred ***', 16, 1)

DECLARE @job_name NVARCHAR(256) = (SELECT name FROM msdb.dbo.sysjobs WHERE job_id = $(ESCAPE_SQUOTE(JOBID)))
DECLARE @email_profile NVARCHAR(256) = 'SQLServer Alerts'
DECLARE @emailrecipients NVARCHAR(500) = 'EmailAddr@email.com'
DECLARE @subject NVARCHAR(MAX) = 'SQL Server Agent Job Failure Report: ' + @@SERVERNAME
DECLARE @msgbodynontable NVARCHAR(MAX) = 'SQL Server Agent Job Failure Report For: "' + @job_name + '"'

--Dump report data to a temp table to be put into XML formatted HTML table to email out
SELECT sjh.[server]
    ,sj.NAME
    ,sjh.step_id
    ,sjh.[message]
    ,sjh.run_date
    ,sjh.run_time
INTO #TempJobFailRpt
FROM msdb..sysjobhistory sjh
INNER JOIN msdb..sysjobs sj ON (sj.job_id = sjh.job_id)
WHERE run_date = convert(INT, convert(VARCHAR(8), getdate(), 112))
    AND run_status != 4 -- Do not show status of 4 meaning in progress steps
    AND run_status != 1 -- Do not show status of 1 meaning success
    AND NAME = @job_name
ORDER BY run_date

IF EXISTS (
        SELECT *
        FROM #TempJobFailRpt
        )
BEGIN

-----Build report to HTML formatted email using FOR XML PATH
DECLARE @tableHTML NVARCHAR(MAX) = '
<html>
<body>
    <H1>' + @msgbodynontable + '</H1>
        <table border="1" style=
        "background-color: #C0C0C0; border-collapse: collapse">
        <caption style="font-weight: bold">
            ****** 
            Failure occurred in the SQL Agent job named: ''' + @job_name + ''' in at least one of the steps. 
            Below is the job failure history detail for ALL runs of this job today without needing to connect to SSMS to check.
            ******
        </caption>

<tr>
    <th style="width:25%; text-decoration: underline">SQL Instance</th>
    <th style="text-decoration: underline">Job Name</th>
    <th style="text-decoration: underline">Step</th>
    <th style="text-decoration: underline">Message Text</th>
    <th style="text-decoration: underline">Job Run Date</th>
    <th style="text-decoration: underline">Job Run Time</th>
</tr>' + CAST((
            SELECT td = [server]
                ,''
                ,td = NAME
                ,''
                ,td = step_id
                ,''
                ,td = [message]
                ,''
                ,td = run_date
                ,''
                ,td = run_time
            FROM #TempJobFailRpt a
            ORDER BY run_date
            FOR XML PATH('tr')
                ,TYPE
                ,ELEMENTS XSINIL
            ) AS NVARCHAR(MAX)) + '
    </table>
</body>
</html>';

EXEC msdb.dbo.sp_send_dbmail @profile_name = @email_profile
    ,@recipients = @emailrecipients
    ,@subject = @subject
    ,@body = @tableHTML
    ,@body_format = 'HTML'

--Drop Temp table
    DROP TABLE #TempJobFailRpt
END
ELSE
BEGIN
    PRINT '*** No Records Generated ***' 
    DROP TABLE #TempJobFailRpt
END
END

ฉันรู้ว่านี่เป็นเธรดเก่า แต่โซลูชันโดย @Crazy Ivan ทำงานได้ดี - ฉันสามารถยืนยันได้ว่าทำงานได้กับ SQL Server 2012
Michael
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.