avvisare quando un lavoro in una categoria di lavoro fallisce


11

È possibile impostare un avviso in SQL Server 2008 che invierà un'e-mail ogni volta che un lavoro in una categoria specifica fallisce?

Mi chiedo perché vorrei impostare un'e-mail ogni volta che un abbonamento SSRS fallisce - e tutti questi abbonamenti sono lavori nella categoria Server di report .

EDIT : si scopre che quando una sottoscrizione SSRS fallisce, il lavoro stesso non fallisce, quindi la mia domanda non si applica all'utilizzo del monitoraggio delle sottoscrizioni SSRS. Tuttavia, vorrei comunque sapere per altri lavori che eseguiamo nel nostro ambiente


Almeno un passo fallisce? La mia risposta di seguito esamina i lavori nella categoria "Server di report", ma se si desidera solo tutti i lavori è possibile rimuovere l'intera AND EXISTSparte di INSERT/SELECT. E probabilmente cambi il nome ReportServerJob_FailQueuein qualcosa di più generico. :-)
Aaron Bertrand

Sfortunatamente, nessun passo fallisce, ma sono fiducioso di poter trovare qualche altro meccanismo di monitoraggio!
JHFB,

Risposte:


10

È possibile creare un processo che controlli la tabella msdb.dbo.sysjobhistory ogni minuto (o per quanto frequentemente si desideri). Potresti voler implementare una tabella delle code in modo da poter inviare il messaggio solo per un singolo errore di istanza una sola volta.

USE msdb;
GO

CREATE TABLE dbo.ReportServerJob_FailQueue
(
  job_id UNIQUEIDENTIFIER,
  run_date INT,
  run_time INT, -- horrible schema, just matching sysjobhistory
  sql_message_id INT,
  sent BIT NOT NULL DEFAULT 0,
  PRIMARY KEY (job_id, run_date, run_time)
);

Quindi il tuo codice, che puoi programmare in un lavoro, diventa:

INSERT dbo.ReportServerJob_FailQueue
  (job_id, run_date, run_time, sql_message_id)
SELECT job_id, run_date, run_time, sql_message_id
FROM msdb.dbo.sysjobhistory AS h
WHERE step_id = 0 
AND run_status = 0
AND EXISTS 
(
  SELECT 1 FROM msdb.dbo.sysjobs AS j
    INNER JOIN msdb.dbo.syscategories AS c
    ON j.category_id = c.category_id
    WHERE j.job_id = h.job_id
   AND c.name = 'Report Server'
)
AND NOT EXISTS 
(
  SELECT 1 FROM dbo.ReportServerJob_FailQueue
    WHERE job_id = h.job_id
    AND run_date = h.run_date
    AND run_time = h.run_time
);

Ora suppongo che tu voglia inviare una singola e-mail per ogni errore, quindi anche questo potrebbe far parte del lavoro (o parte di un lavoro diverso, anche se non è necessariamente saggio):

DECLARE 
  @subject NVARCHAR(4000),
  @body NVARCHAR(4000),
  @name SYSNAME,
  @id UNIQUEIDENTIFIER,
  @date INT,
  @time INT,
  @msg INT;

DECLARE c CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR SELECT q.job_id, q.run_date, q.run_time, q.sql_message_id, j.name
  FROM dbo.ReportServerJob_FailQueue AS q
  INNER JOIN msdb.dbo.sysjobs AS j
  ON q.job_id = j.job_id
  WHERE q.sent = 0;

OPEN c;

FETCH NEXT FROM c INTO @id, @date, @time, @msg, @name;

WHILE @@FETCH_STATUS = 0
BEGIN

  SET @subject = 'Report Server job ' + @name + ' failed.';
  SET @body = 'Error number: ' + RTRIM(@msg);

  BEGIN TRY
    EXEC msdb.dbo.sp_send_dbmail 
      @profile_name = 'default',     -- you may need to change this
      @recipients   = 'foo@bar.com', -- you will need to change this
      @subject      = @subject,
      @body         = @body;

    UPDATE dbo.ReportServerJob_FailQueue
      SET sent = 1 
      WHERE job_id = @id
      AND run_date = @date
      AND run_time = @time;
  END TRY
  BEGIN CATCH
    PRINT 'Will have to try that one again later.';
  END

  FETCH NEXT FROM c INTO @id, @date, @time, @msg, @name;
END

CLOSE c; DEALLOCATE c;

Ci sono anche altre opzioni:

  • pull in sysjobhistory.message
  • guarda i singoli passaggi che hanno fallito
  • inviare un messaggio per qualsiasi lavoro solo una volta in n minuti / ore anche se ci sono più errori
  • inviare una singola e-mail con un elenco di tutti i lavori non riusciti, anziché una e-mail per ogni errore
  • potresti voler includere run_date e run_time nel messaggio, poiché l'e-mail potrebbe non essere inviata o ricevuta abbastanza rapidamente da essere una misura accurata di quando il lavoro è effettivamente fallito (non l'ho incluso qui perché le loro orribili scelte sul tipo di dati fare della formattazione quella roba una PITA reale)
  • probabilmente vorrai ripulire le vecchie righe dopo un po 'di tempo, quindi potrebbe essere desiderato anche un comando di eliminazione

Se Posta elettronica database non è già impostata, consultare questa esercitazione .

È inoltre possibile utilizzare strumenti di terze parti (ad esempio SQL Sentry Event Manager ) che semplificheranno notevolmente questa operazione. Informativa completa: lavoro per SQL Sentry.


0

In base alla tua modifica, questa sarebbe solo un'estensione della risposta di Aaron, per quanto riguarda gli errori di sottoscrizione SSRS stessi (non solo il processo dell'agente SQL). Suggerirei semplicemente di aggiungere un passaggio al lavoro di monitoraggio del lavoro, oppure potresti farlo come un lavoro separato del tutto.

Per ottenere lo stato dell'abbonamento è sufficiente controllare la ReportServer.dbo.ExecutionLog3 vista . La Statuscolonna mostrerà tutto tranne che rsSuccesssugli errori. Basta filtrare per RequestType = 'Subscription'. Ti consigliamo di includere un po 'di controllo del tempo, in modo da non controllare tutti i record ogni volta. Se si esegue il lavoro ogni 15 minuti, controllare solo TimeStartper gli ultimi 15 minuti.

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.