작업이 실패 할 때 SQL Server에서 오류 세부 정보를 전자 메일로 보내려면 어떻게해야합니까? 다음과 같습니다. JOB RUN:

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).

실패 원인을 확인하려면 SQL Server Management Studio에서 인스턴스로 이동하여 작업을 찾은 다음 실행 기록을 확인해야합니다. 넓은 환경에서는 지속적으로이 작업을 수행해야하는 것이 고통 스러울 수 있습니다.

이상적인 경고 전자 메일에는 실패 이유가 미리 포함되어 있으므로 솔루션 작업을 바로 시작할 수 있습니다.

이 문제에 대한 이 솔루션 에 익숙 합니다. 누구든지 그것에 대해 경험이 있습니까? 단점은 다음과 같습니다.

  1. 당신이 가진 모든 직업에 새로운 단계를 추가해야합니다.
  2. 아무도 경고 절차를 망쳐 놓지 않도록기도해야합니다. spDBA_job_notification

더 나은 해결책을 찾은 사람이 있습니까?



답변

당신이 할 수있는 것은 생각 일 뿐이고 생각을 버리는 것입니다.

msdb에서 작업 테이블을 주기적으로 검사하여 실패한 것으로 표시되는지 확인하는 단일 작업을 작성하십시오. 이는 양호한 T-SQL 쿼리 로 수행 할 수 있습니다 . 그런 다음 sysjobsteps 테이블로 이동하여 작업에 대한 출력 로그가 설정되어 있는지 확인할 수 있습니다. 저장 프로 시저가 해당 파일을 첨부하는 이메일을 보내도록하십시오. 서버를 건드리지 않고도 작업이 처음부터 실패한 것을 정확하게 볼 수 있습니다.

그런 다음 PowerShell 스크립트가 이벤트 로그에서 오류를 확인하도록 할 수도 있습니다. 그것은 당신이 찾고있는 메시지 유형을 정확하게 얻기 위해 꽤 좋은 비트를 필터링 할 수 있습니다. 주기적으로 실행되도록 SQL 에이전트 작업으로 설정할 수 있습니다. 그런 다음 PowerShell 스크립트에서 전자 메일 cmdlet을 사용하여 메시지를 찾으면 메시지를 보냅니다.

여기에 아이디어를 가져 왔습니다.


답변

나는 위에서 언급 한 아이디어에 대한 경험이 있다 . 좋지만, 더 좋은 생각은 Shawn이 말한 것과 같은 일을하는 것입니다.

우리가 한 일은 5 분마다 실행되는 작업을 만들고 작업 실패에 대한 MSDB 테이블을 스캔하는 것이 었습니다. 실패한 각 작업에 대해 SP spDBA_job_notification 은 자체 ID로 실행되므로 SP는 MSDB 히스토리 단계에서 오류가 있는지 스캔하여 모두 이메일로 보냅니다 . SP 문서에서 : “저장 프로시 저는 작업 ID를 사용하여 해당 작업에 대한 최신 오류 메시지에 대한 msdb 에이전트 테이블을 쿼리합니다.”

따라서 모든 작업을 변경하는 대신 모든 😉 작업을 수행하는 단일 작업을 작성하는 것이 좋습니다.

또 다른 아이디어는 오류 / 실패의 경우 모든 작업을 Windows 이벤트 뷰어에 쓰도록 설정하고 확장 된 proc xp_ReadErrorLog 또는 네트워크에 이미있는 경우 자동 도구를 사용하여 해당 작업 에서 읽도록 설정하는 것입니다 . 예를 들어 HPOV 를 사용 하여 시스템 문제를 확인하고 모든 이벤트 뷰어 오류에 대해 간단한 경고를 구성 할 수 있습니다 (사용자 정의 작업이나 절차가 필요하지 않음).


답변

이것을 시도하고 TSQL에서 필요에 따라 변수를 연결하십시오. 여기서 핵심은 이것을 각 개별 SQL 에이전트 작업의 마지막 단계로 두는 것입니다.하지만 위의 각 작업 단계는 실패 또는 성공 여부에 관계없이 다음 단계로 이동해야합니다 … 대부분 잘 작동하지만 제발 실행 한 모든 문제를보고하십시오. 우리는 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