web-dev-qa-db-ja.com

ジョブが失敗したときに、SQL Serverからエラーの詳細をメールで受け取るにはどうすればよいですか?

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でインスタンスに移動し、ジョブを見つけて、その実行履歴を表示する必要があります。大規模な環境では、これを常に実行しなければならないのは面倒です。

理想的なアラートメールには、失敗の理由が事前に含まれ、ソリューションに直接取り掛かることができます。

私はこの問題の this solution に精通しています。誰かがそれについて何か経験がありますか?その欠点は次のとおりです。

  1. あなたが持っている仕事ごとに新しいステップを追加する必要があり、そして
  2. 誰もアラートプロシージャspDBA_job_notificationを台無しにしないように祈る必要があります

誰かがより良い解決策を考え出しましたか?

14
Nick Chammas

あなたがするかもしれない何かはただの考えであり、アイデアを捨てます...

Msdbのジョブテーブルを定期的にチェックして失敗したジョブがあるかどうかを確認する単一のジョブを作成します。これは、適切な T-SQLクエリ で実行できます。次に、sysjobstepsテーブルに移動して、ジョブの出力ログが設定されているかどうかを確認します。ストアドプロシージャに、そのファイルを添付した電子メールを送信させる。サーバーに触れることなく、ジョブの最初から失敗までの処理を正確に確認できます。

次に、PowerShellスクリプトでエラーのイベントログを確認することもできます。それはあなたが探しているメッセージタイプを正確に取得するためにかなり良いビットをフィルタリングすることを可能にします。これをSQLエージェントジョブとして設定して、定期的に実行することができます。次に、PowerShellスクリプトでemailコマンドレットを使用して、メッセージが見つかった場合にメッセージを送信します。

ここで得られたアイデアは、私が考えたものの一部です。

10
user507

前述のアイデア の経験があります。それは良いことですが、より良いアイデアは、ショーンが言ったようなことをすることです。

5分ごとに実行され、ジョブの失敗についてMSDBテーブルをスキャンするジョブを作成しました。失敗した各ジョブについて、SPspDBA_job_notificationを独自のIDで実行するので、SPは、MSDB履歴ステップでエラーをスキャンし、それらすべてにメールを送信します。 SPのドキュメントから:「ストアドプロシージャはジョブIDを使用して、そのジョブの最新のエラーメッセージをmsdbエージェントテーブルに照会します。」

したがって、すべてのジョブを変更するのではなく、すべてを実行する単一のジョブを作成することをお勧めします;-)。

別のアイデアは、エラー/失敗の場合にすべてのジョブをWindowsイベントビューアに書き込むように設定し、 extended proc xp_ReadErrorLog または自動ツールを使用してそこから読み取ることです(ネットワークに既にある場合)。たとえば、 [〜#〜] hpov [〜#〜] を使用してシステムの問題を確認し、すべてのイベントビューアーエラーに対して単純なアラートを構成できます(カスタムジョブや手順は必要ありません)。

3
Marian

これを試して、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) = '[email protected]'
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
2
user72649