Como o SQL Server pode me enviar por e-mail os detalhes do erro quando um trabalho falha?

14

O SQL Server permite configurar um trabalho para enviar alertas por email quando ele falhar. Essa é uma maneira simples e eficaz de monitorar seus trabalhos. No entanto, esses alertas não incluem nenhum detalhe - apenas um aviso de sucesso ou falha.

Se um trabalho falhar, será como um email de alerta típico será:

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

Para determinar a causa da falha, você deve navegar para a instância no SQL Server Management Studio, encontrar o trabalho e exibir seu histórico de execução. Em um ambiente amplo, pode ser uma dor ter que fazer isso constantemente.

O email de alerta ideal incluiria o motivo da falha antecipadamente e permitiria que você trabalhasse diretamente na solução.

Estou familiarizado com esta solução para este problema. Alguém tem alguma experiência com isso? Suas desvantagens são:

  1. você precisa adicionar uma nova etapa a cada trabalho que tiver e
  2. você tem que rezar para que ninguém estrague o processo de alerta, spDBA_job_notification

Alguém veio com uma solução melhor?

Nick Chammas
fonte

Respostas:

10

Algo que você pode fazer é apenas um pensamento, jogando idéias fora ...

Crie um único trabalho que verifique periodicamente a tabela de trabalhos no msdb para ver se algum trabalho aparece como com falha, isso pode ser feito com uma boa consulta T-SQL . Em seguida, você pode entrar na tabela sysjobsteps e ver se um log de saída está definido para o trabalho. Faça com que um procedimento armazenado envie um email anexando esse arquivo a ele. Você seria capaz de ver exatamente o que o trabalho fazia desde o início até a falha sem precisar tocar no servidor.

Em seguida, o script do PowerShell também pode verificar se há erros no log de eventos. Ele permite filtrar um pouco bastante para obter exatamente quais tipos de mensagens você está procurando. Você pode configurá-lo como um trabalho do SQL Agent para executar periodicamente. Em seguida, no script do PowerShell, use o cmdlet de email para enviar a mensagem, se encontrar.

Ideias muito buscadas aqui, apenas algumas em que pensei.


fonte
3

Eu tenho experiência com a idéia acima mencionada . É bom, mas uma idéia melhor seria fazer algo como Shawn disse.

O que fizemos foi realizar um trabalho que é executado a cada 5 minutos e verifica as tabelas do MSDB sobre falhas de trabalho. Para cada trabalho que teve uma falha, executamos o SP spDBA_job_notification com seu próprio ID, para que o SP verifique se há erros nas etapas do histórico do MSDB e envie por e-mail a todos eles. Na documentação do SP: "O procedimento armazenado usa o ID do trabalho para consultar as tabelas do agente msdb para obter a mensagem de erro mais recente para esse trabalho."

Então, em vez de apenas mudar todos os trabalhos, crie melhor um que faça tudo ;-).

Outra idéia é definir todos os trabalhos para gravar no Windows Event Viewer em caso de erros / falhas e ler a partir daí com o proc xp_ReadErrorLog estendido ou uma ferramenta automática, se você já o tiver em sua rede. Por exemplo, usamos o HPOV para verificar quaisquer problemas do sistema e podemos configurar um alerta simples para todos os erros do visualizador de eventos (sem necessidade de qualquer tarefa ou procedimento personalizado).

Marian
fonte
2

Faça uma tentativa e basta conectar suas variáveis ​​conforme necessário no TSQL. A chave aqui é colocar isso como a última etapa de cada tarefa individual do agente SQL, mas cada etapa acima precisa ir para NEXT STEP, seja FAILURE ou SUCCESS ... Funciona para mim muito bem na maior parte, mas por favor relate quaisquer problemas que encontrar. Como estamos no SQL Server 2008 R2, é aqui que é usado onde eu o configurei atualmente.

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

fonte
Eu sei que isto é uma discussão antiga, mas a solução por @Crazy Ivan funciona um tratamento - Eu posso confirmar que funciona no SQL Server 2012
Michael