оповещение, когда любая работа в категории работы терпит неудачу

11

Можно ли настроить предупреждение в SQL Server 2008, которое будет отправлять электронную почту в случае сбоя задания в определенной категории?

Мне интересно, потому что я хотел бы настроить электронную почту в случае сбоя подписки SSRS - и все эти подписки являются заданиями в категории « Сервер отчетов» .

РЕДАКТИРОВАТЬ - оказывается, что при сбое подписки SSRS само задание не перестает работать, поэтому мой вопрос не будет применяться к использованию мониторинга подписки SSRS. Однако я все еще хотел бы знать для других рабочих мест, которые мы выполняем в нашей среде

JHFB
источник
По крайней мере, шаг проваливается? В моем ответе ниже рассматриваются задания в категории «Сервер отчетов», но если вам нужны все задания, вы можете удалить всю эту AND EXISTSчасть INSERT/SELECT. И, вероятно, изменить имя ReportServerJob_FailQueueна что-то более общее. :-)
Аарон Бертран
К сожалению, ни один шаг не проходит - но я уверен, что смогу придумать какой-нибудь другой механизм мониторинга!
JHFB

Ответы:

10

Вы можете создать задание, которое проверяет таблицу msdb.dbo.sysjobhistory каждую минуту (или сколько угодно часто). Возможно, вы захотите реализовать таблицу очередей, чтобы вы когда-либо отправляли сообщение только для одного отдельного экземпляра.

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

Итак, ваш код, который вы можете запланировать на работе, становится:

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

Теперь я предполагаю, что вы хотите отправить отдельное электронное письмо для каждого сбоя, так что это может быть частью работы (или частью другой работы, хотя это не обязательно целесообразно):

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;

Есть и другие варианты:

  • тянуть в sysjobhistory.message
  • посмотрите на отдельные шаги, которые не удалось
  • отправлять сообщение для любой работы только один раз за n минут / часов, даже если есть несколько сбоев
  • отправлять одно электронное письмо со списком всех неудачных заданий, а не по электронной почте для каждого сбоя
  • Возможно, вы захотите включить в сообщение run_date и run_time, так как электронное письмо может быть отправлено или получено недостаточно быстро, чтобы быть точным показателем того, когда задание действительно не удалось (я не включил его здесь, потому что их ужасный выбор типов данных сделай форматирование этого материала королевской питой)
  • Вы, вероятно, захотите очистить старые строки через некоторое время, поэтому может потребоваться и команда очистки

Если компонент Database Mail еще не настроен, обратитесь к этому руководству .

Вы также можете использовать сторонние инструменты (например, SQL Sentry Event Manager ), которые значительно упростят эту задачу. Полное раскрытие: я работаю на SQL Sentry.

Аарон Бертран
источник
0

Исходя из ваших правок, это будет просто продолжение ответа Аарона, касающегося самих сбоев подписки SSRS (а не только задания агента SQL). Я бы предложил просто добавить шаг к заданию по мониторингу работы, или вы можете сделать это как отдельную работу в целом.

Чтобы получить статус подписки, вам нужно просто проверить ReportServer.dbo.ExecutionLog3 вид . StatusКолонка покажет ничего , кроме rsSuccessпо отказам. Просто фильтр для RequestType = 'Subscription'. Вы захотите включить проверку времени, чтобы не проверять все записи каждый раз. Если вы запускаете задание каждые 15 минут, просто проверьте TimeStartпоследние 15 минут.


источник