W jaki sposób SQL Server może przesłać mi e-mailem szczegóły błędu, gdy zadanie się nie powiedzie?

14

SQL Server pozwala skonfigurować zadanie wysyłania powiadomień e-mail, gdy się nie powiedzie. Jest to prosty i skuteczny sposób monitorowania zadań. Alerty te nie zawierają jednak żadnych szczegółów - tylko powiadomienie o sukcesie lub niepowodzeniu.

Jeśli zadanie nie powiedzie się, będzie wyglądać typowy e-mail z ostrzeżeniem:

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

Aby ustalić przyczynę niepowodzenia, musisz przejść do wystąpienia w SQL Server Management Studio, znaleźć zadanie i przejrzeć historię jego wykonania. W dużym środowisku ciągłe robienie tego może być uciążliwe.

Idealny e-mail z ostrzeżeniem zawiera z góry przyczynę niepowodzenia i pozwala od razu przystąpić do pracy nad rozwiązaniem.

Znam to rozwiązanie tego problemu. Czy ktoś ma z tym jakieś doświadczenie? Jego wady to:

  1. musisz dodać nowy krok do każdej pracy i
  2. musicie się modlić, aby nikt nie zadziałał na alarm, spDBA_job_notification

Czy ktoś wymyślił lepsze rozwiązanie?

Nick Chammas
źródło

Odpowiedzi:

10

Coś, co możesz zrobić, to tylko myśl, wyrzucanie pomysłów ...

Utwórz pojedyncze zadanie, które okresowo sprawdza tabelę zadań w msdb, aby sprawdzić, czy jakieś zadania nie pokazują się jako zakończone niepowodzeniem, co można wykonać za pomocą dobrego zapytania T-SQL . Następnie możesz przejść do tabeli sysjobsteps i sprawdzić, czy dla zadania ustawiony jest dziennik wyjściowy. Poproś, aby procedura składowana wysłała wiadomość e-mail dołączającą do tego pliku. Będziesz mógł zobaczyć dokładnie, co zrobiło zadanie od początku do niepowodzenia, bez konieczności dotykania serwera.

Następnie skrypt skryptu PowerShell może również sprawdzić dziennik zdarzeń pod kątem błędów. Pozwala to całkiem dobrze odfiltrować, aby uzyskać dokładnie to, jakiego rodzaju wiadomości szukasz. Można ustawić to jako zadanie agenta SQL, aby uruchamiało się okresowo. Następnie w skrypcie PowerShell użyj polecenia cmdlet e-mail, aby wysłać wiadomość, jeśli ją znajdzie.

Daleko idące pomysły tutaj, tylko o których myślałem.


źródło
3

Mam doświadczenie z wyżej wymienionym pomysłem . To dobrze, ale lepszym pomysłem byłoby zrobienie czegoś takiego, jak powiedział Shawn.

Zrobiliśmy zadanie, które będzie uruchamiane co 5 minut i skanuje tabele MSDB pod kątem awarii zadań. Dla każdego zadania, które uległo awarii, uruchomilibyśmy SP spDBA_job_notification z własnym identyfikatorem, więc SP skanuje kroki historii MSDB w poszukiwaniu błędów i wysyła je wszystkie pocztą e-mail. Z dokumentacji SP: „Procedura przechowywana używa identyfikatora zadania do przeszukiwania tabel agenta msdb w poszukiwaniu najnowszego komunikatu o błędzie dla tego zadania”.

Zamiast zmieniać każdą pracę, lepiej stwórz jedną, która zrobi wszystko ;-).

Innym pomysłem jest ustawienie wszystkich zadań do zapisywania w Podglądzie zdarzeń systemu Windows w przypadku błędów / awarii i odczytywania stamtąd za pomocą rozszerzonego proc xp_ReadErrorLog lub automatycznego narzędzia, jeśli masz je już w swojej sieci. Na przykład użyliśmy HPOV do sprawdzenia wszelkich problemów systemowych i mogliśmy skonfigurować prosty alert dla wszystkich błędów podglądu zdarzeń (nie ma potrzeby wykonywania żadnych niestandardowych zadań ani procedur).

Marian
źródło
2

Spróbuj i po prostu podłącz swoje zmienne w razie potrzeby w TSQL. Kluczem tutaj jest umieszczenie tego jako ostatniego kroku dla każdego pojedynczego zadania agenta SQL, ale każdy krok zadania powyżej musi przejść do NASTĘPNEGO KROKU, niezależnie od tego, czy jest to AWARIA, czy SUKCES ... W większości przypadków działa dobrze, ale proszę zgłoś wszelkie napotkane problemy. Korzystamy z SQL Server 2008 R2, więc tutaj jest używany tam, gdzie go skonfigurowałem.

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

źródło
Wiem, że to stary wątek, ale rozwiązanie autorstwa @Crazy Ivan działa na ucztę - mogę potwierdzić, że działa na SQL Server 2012
Michael