Имея несколько триггеров, вызывающих задание, вы вводите условие гонки, поэтому те же триггеры, вызывающие гонку, вряд ли смогут ее решить.Вам нужен внешний наблюдатель.
Вы можете попробовать ...
Создать новую таблицу, например:
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