У меня есть несколько заданий агента SQL Server, которые должны выполняться последовательно. Чтобы иметь хороший обзор работ, которые должны быть выполнены, я создал основную работу, которая вызывает другие работы с вызовом EXEC msdb.dbo.sp_start_job N'TEST1'
. Завершение происходит sp_start_job
мгновенно (шаг работы 1), но затем я хочу, чтобы моя основная работа ждала, пока работа TEST1
не будет завершена, прежде чем вызвать следующую работу.
Итак, я написал этот небольшой скрипт, который начинает выполняться сразу после вызова задания (шаг задания 2) и заставляет основное задание ждать, пока подзадача не будет завершена:
WHILE 1 = 1
BEGIN
WAITFOR DELAY '00:05:00.000';
SELECT *
INTO #jobs
FROM OPENROWSET('SQLNCLI', 'Server=TESTSERVER;Trusted_Connection=yes;',
'EXEC msdb.dbo.sp_help_job @job_name = N''TEST1'',
@execution_status = 0, @job_aspect = N''JOB''');
IF NOT (EXISTS (SELECT top 1 * FROM #jobs))
BEGIN
BREAK
END;
DROP TABLE #jobs;
END;
Это работает достаточно хорошо. Но я чувствую, что более разумные и / или более безопасные ( WHILE 1 = 1
?) Решения должны быть возможными.
Мне любопытно следующее: надеюсь, вы сможете дать мне некоторые идеи:
- Какие проблемы с этим подходом?
- Можете ли вы предложить лучший способ сделать это?
( Сначала я разместил этот вопрос в StackOverflow , потому что сосредоточился на улучшении кода. Все еще в силе. Но я полагаю, что люди здесь, в общем, будут умнее говорить о том, почему я не должен пытаться делать это так, как я » Я делаю это сейчас, или предоставить хорошие альтернативы.)
РЕДАКТИРОВАТЬ (25 июля)
По-видимому, с моим сценарием не так уж и много проблем, в связи с небольшим количеством ответов, указывающих на проблемы с ним :-) Альтернативой этому виду сценариев является использование инструмента, предназначенного для этих задач. задачи (например, SQL Sentry Event Manager или ...) - или написать такой инструмент самостоятельно. Мы не будем покупать такой инструмент в моей нынешней компании, поэтому сейчас я просто буду придерживаться сценария.
источник
Ответы:
Отказ от ответственности: я работаю на SQL Sentry.
У нашего продукта SQL Sentry Event Manager есть средство, созданное именно для этого: объединять задания в группы и распределять их по различным заказам рабочих процессов.
Я начал использовать SQL Sentry несколько лет назад, еще до того, как присоединился к компании, чтобы делать именно это. Мне нужен был способ начать задание восстановления на нашем тестовом сервере сразу после завершения резервного копирования на производстве.
Первоначально я реализовал лишь существенный буфер между временем начала задания резервного копирования и временем начала восстановления. Это было не совсем надежно; поскольку время резервного копирования варьировалось, буфер часто оставлял нам потерянное время, когда восстановление не началось, хотя могло бы. И иногда буфера было недостаточно.
Следующее, что я реализовал, было похоже на то, что у вас есть - я написал задание на тестовом сервере, которое началось вскоре после запланированного резервного копирования, и продолжал опрашивать, чтобы увидеть, когда задание было завершено. Позже это было исправлено, чтобы просто выполнить второй шаг в задании резервного копирования, которое обновило таблицу на тестовом сервере. Ничего особенного, за исключением того, что заданию восстановления нужно было только наблюдать за таблицей локально, а не удаленно отслеживать историю заданий. Вспоминая, что это могло быть триггером в этой таблице, который вызывал,
sp_start_job
так что задание не нужно было запускать каждые n минут (или планировать вообще)Конечное решение заключалось в том, чтобы объединить задания вместе ... после завершения резервного копирования на сервере A менеджер событий запускает задание восстановления на сервере B. И если было третье задание и четвертое задание, или условная логика, основанная на том, что делать когда работа терпит неудачу против успеха и т. д., все это можно объяснить. Дизайнер рабочих процессов напомнит вам немного об SSIS:
Основная механика того, что я описываю, это, конечно, не ракетная хирургия. Вы могли бы написать этот тип обертки для цепей самостоятельно, если бы вы сели и сделали это. Просто предоставлю вам одну альтернативу, где вам не нужно.
источник
Основная проблема с вашим подходом заключается в том, что вы должны постоянно зацикливаться, пока что-то не произойдет (что может быть очень долго или даже никогда), и это не совсем правильно. Вот почему я думаю, что вы задаете вопрос.
Итак, как насчет использования подхода на основе данных к вашей проблеме? Например, создайте таблицу аудита, в которую каждое задание записывается при запуске и завершении:
Создайте таблицу «обработки», в которой перечислены все задания и порядок их выполнения:
Создайте триггер вставки в таблице аудита, чтобы после завершения задания и вставки записи аудита триггер запрашивал таблицу обработки для следующего задания (по порядку выполнения) и затем запускал ее.
Преимущества этого подхода:
НТН
источник