作业失败时,如何让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).

若要确定失败的原因,您必须导航到SQL Server Management Studio中的实例,找到该作业,并查看其执行历史记录。在大型环境中,必须不断执行此操作可能会很痛苦。

理想的警报电子邮件应包括预先的故障原因,并让您直接进行解决方案的开发。

我对这个问题的解决方案很熟悉。有人有经验吗?它的缺点是:

  1. 您必须为每项工作添加新步骤,并且
  2. 您必须祈祷没有人弄乱警报进程, spDBA_job_notification

有谁想出更好的解决方案?

Answers:


10

您可能会做的只是个想法,将想法扔掉...

创建单个作业,该作业定期检查msdb中的作业表以查看是否有任何作业显示为失败,这可以通过良好的T-SQL查询来完成。然后,您可以进入sysjobsteps表,查看是否为该作业设置了输出日志。让存储过程发送一封电子邮件,将其附加到该文件。您将能够准确地了解工作从开始到失败的全部过程,而无需接触服务器。

然后还可以让PowerShell脚本检查事件日志中是否有错误。它使您可以过滤掉相当多的内容,以准确获取所需的消息类型。您可以将其设置为SQL Agent作业以定期运行。然后在PowerShell脚本中使用电子邮件cmdlet发送消息(如果找到了一条消息)。

这里牵强的想法,只是我想到的一些。


3

对上述想法有经验。很好,但是更好的主意是做类似肖恩所说的事情。

我们要做的是使作业每5分钟运行一次,并扫描有关作业失败的MSDB表。对于每个失败的作业,我们将使用其自己的ID 运行SP spDBA_job_notification,因此SP将扫描MSDB历史记录步骤以查找错误并通过电子邮件将其全部发送。从SP文档中:“存储过程使用作业ID来查询msdb代理表中有关该作业的最新错误消息。”

因此,与其仅仅改变每一项工作,不如创造一个可以完成所有工作的项目;-)。

另一个想法是将所有作业设置为在发生错误/故障时写入Windows Event Viewer,并使用扩展的proc xp_ReadErrorLog或自动工具(如果您已经在网络中)从那里进行读取。例如,我们使用HPOV检查任何系统问题,并可以为所有事件查看器错误配置简单警报(无需任何自定义作业或过程)。


2

试试看,然后根据需要在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

我知道这是一个旧线程,但是@Crazy Ivan的解决方案可以有效-我可以确认它可以在SQL Server 2012上使用
Michael
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.