Come è possibile che SQL Server mi invii tramite e-mail i dettagli dell'errore in caso di errore di un processo?


14

SQL Server consente di configurare un processo per l'invio di avvisi e-mail in caso di errore. Questo è un modo semplice ed efficace per monitorare i tuoi lavori. Tuttavia, questi avvisi non includono alcun dettaglio, ma solo un avviso di successo o fallimento.

Se un lavoro fallisce, ecco come apparirà una tipica email di avviso:

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

Per determinare la causa dell'errore, è necessario passare all'istanza in SQL Server Management Studio, trovare il lavoro e visualizzarne la cronologia di esecuzione. In un grande ambiente può essere una seccatura doverlo fare costantemente.

L'e-mail di avviso ideale includerebbe il motivo dell'errore in anticipo e ti consentirà di iniziare subito a lavorare sulla soluzione.

Conosco questa soluzione a questo problema. Qualcuno ha avuto qualche esperienza con questo? Gli svantaggi sono:

  1. devi aggiungere un nuovo passaggio ogni lavoro che hai, e
  2. devi pregare che nessuno rovini il proc di allerta, spDBA_job_notification

Qualcuno ha trovato una soluzione migliore?

Risposte:


10

Qualcosa che potresti fare è solo un pensiero, scartare idee ...

Creare un singolo lavoro che controlla periodicamente la tabella dei lavori in msdb per vedere se alcuni lavori vengono visualizzati come non riusciti, che può essere fatto con una buona query T-SQL . Quindi è possibile accedere alla tabella sysjobsteps e verificare se per il processo è impostato un registro di output. Chiedi a una procedura memorizzata di inviare un'email allegando quel file. Saresti in grado di vedere esattamente cosa ha fatto il lavoro dall'inizio al fallimento senza dover toccare il server.

Quindi potrebbe anche fare in modo che lo script PowerShell controlli gli errori nel registro eventi. Ti consente di filtrare un po 'abbastanza bene per ottenere esattamente quali tipi di messaggi stai cercando. È possibile configurarlo come processo SQL Agent da eseguire periodicamente. Quindi nello script di PowerShell utilizzare il cmdlet di posta elettronica per inviare il messaggio se ne trova uno.

Idee di gran lunga prese qui, solo alcune a cui ho pensato.


3

Ho esperienza con l'idea di cui sopra . È buono, ma un'idea migliore sarebbe quella di fare qualcosa come Shawn ha detto.

Quello che abbiamo fatto è stato quello di creare un lavoro che viene eseguito ogni 5 minuti e di scansionare le tabelle MSDB sugli errori dei lavori. Per ogni lavoro che presentava un errore avremmo eseguito SP spDBA_job_notification con il proprio ID, quindi SP eseguirà la scansione dei passaggi della cronologia di MSDB alla ricerca di errori e li invierà via e-mail. Dalla documentazione SP: "La procedura memorizzata utilizza l'ID lavoro per interrogare le tabelle dell'agente msdb per il messaggio di errore più recente per quel lavoro."

Quindi, invece di cambiare ogni lavoro, è meglio crearne uno che faccia tutto ;-).

Un'altra idea è quella di impostare tutti i lavori per scrivere nel Visualizzatore eventi di Windows in caso di errori / guasti e leggere da lì con proc xp_ReadErrorLog esteso o uno strumento automatico, se già presente nella rete. Ad esempio, abbiamo utilizzato HPOV per verificare eventuali problemi di sistema e configurare un semplice avviso per tutti gli errori del visualizzatore di eventi (non è necessario alcun lavoro o procedura personalizzati).


2

Fai una prova e inserisci le variabili come necessario in TSQL. La chiave qui è quella di mettere questo come l'ultimo passo di ogni singolo lavoro dell'agente SQL ma ogni passaggio del lavoro sopra deve andare al PASSO SUCCESSIVO che sia FALLIMENTO o SUCCESSO ... Funziona per me bene per la maggior parte ma per favore segnala eventuali problemi riscontrati. Siamo su SQL Server 2008 R2, quindi è qui che viene utilizzato dove l'ho impostato attualmente.

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

So che questo è un vecchio thread, ma la soluzione di @Crazy Ivan funziona a meraviglia - posso confermare che funziona su SQL Server 2012
Michael,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.