Как я могу обработать ошибку для sp_job_start? - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть разные триггеры, которые запускают работу.Иногда можно запустить несколько триггеров, чтобы запустить это задание одновременно, и моя первоначальная проверка, чтобы проверить, работает ли задание, не работает должным образом.

DECLARE @JobCount NUMERIC
SET @JobCount = (SELECT COUNT(*)
                   FROM msdb.dbo.sysjobactivity ja
                   JOIN msdb.dbo.sysjobs j
                        ON ja.job_id = j.job_id
                  WHERE j.name = 'JobName'
                        AND ja.start_execution_date IS NOT NULL
                        AND ja.stop_execution_date IS NULL) 

IF @JobCount = 0
  BEGIN
    EXEC msdb.dbo.sp_start_job 
         'JobName'
  END

Это внизу триггеровно если триггеры были инициированы в то же время, он по-прежнему выдает ошибку Error: Request to run job JobName refused because the job is already running from a request by User.BEGIN TRY / CATCH здесь не работает.Я знаю, что в Oracle у вас может быть ИСКЛЮЧЕНИЕ, КОГДА ДРУГИЕ НУЖНО - могу ли я здесь что-нибудь сделать, чтобы просто проигнорировать ошибку , если это произойдет?Я понимаю, что задание все еще выполняется, я просто не хочу выдавать ошибку.

Спасибо

РЕДАКТИРОВАТЬ: Hack Обходной путь добавляет WAITFOR DELAY '00: 00: 01 ', но также открытна другие предложения

1 Ответ

0 голосов
/ 22 ноября 2018

Имея несколько триггеров, вызывающих задание, вы вводите условие гонки, поэтому те же триггеры, вызывающие гонку, вряд ли смогут ее решить.Вам нужен внешний наблюдатель.

Вы можете попробовать ...

Создать новую таблицу, например:

CREATE TABLE JobControl
(
     Id INT IDENTITY(1,1) PRIMARY KEY,
     DateCreated DATETIME DEFAULT CURRENT_TIMESTAMP
)

Измените триггеры, чтобы они вставляливпишите в эту таблицу, а не вызывайте задание.

Создайте второе задание, которое запускается каждые n секунд (или, если хотите, постоянно зацикливается).Это задание проверяет строки в таблице JobControl.Если строки найдены (путем их удаления), запускается основное задание (если оно еще не запущено).Если он удалил строки из этой таблицы и оказалось, что задание уже запущено, он прерывает работу и возвращает строки в следующий раз.

Например:

SET NOCOUNT ON

DECLARE @MYID UNIQUEIDENTIFIER, @rowsDeleted INT
SELECT @MYID=JOB_ID FROM MSDB.DBO.SYSJOBS WHERE NAME='JobName'

CREATE TABLE #enum_job
(
  Job_ID UNIQUEIDENTIFIER,
  Last_Run_Date INT,
  Last_Run_Time INT,
  Next_Run_Date INT,
  Next_Run_Time INT,
  Next_Run_Schedule_ID INT,
  Requested_To_Run INT,
  Request_Source INT,
  Request_Source_ID VARCHAR(100),
  Running INT,
  Current_Step INT,
  Current_Retry_Attempt INT,
  State INT
)

IF @MYID IS NOT NULL
BEGIN
    BEGIN TRAN
        -- delete all rows in table, capture row count
        DELETE J
        FROM JobControl J
        SET @rowsDeleted=@@ROWCOUNT

        -- check running jobs
        INSERT INTO #enum_job
        EXEC master.dbo.xp_sqlagent_enum_jobs 1, NULL

        -- if the job isn't running, and we had rows to delete, run the job
        IF EXISTS (SELECT 1 FROM #enum_job WHERE Job_ID=@MYID AND Running=0) AND @rowsDeleted>0
        BEGIN
            EXEC msdb.dbo.sp_start_job 'JobName'
        END

        -- if the job is already running, and we had rows to delete, roll back
        IF EXISTS (SELECT 1 FROM #enum_job WHERE Job_ID=@MYID AND Running=1) AND @rowsDeleted>0
        BEGIN
            ROLLBACK TRAN
        END
    -- if the transaction is still open, commit it
    IF @@TRANCOUNT>0 COMMIT TRAN
END
...