我有不同的触发因素来启动工作。有时可以设置多个触发器来同时启动该作业,而我的初步检查是看该作业是否运行不正常。
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中别人可能为NULL时可能会有例外-如果发生错误,我可以在这里做任何忽略错误的事情吗?我了解该作业仍在运行,只是不想产生错误。
谢谢
编辑:黑客解决方法是添加WAITFOR DELAY '00:00:01',但也可以接受其他建议
答案 0 :(得分:0)
由于有多个调用该作业的触发器,因此您引入了竞争条件,因此导致该竞争的相同触发器不太可能解决该问题。您需要一个外部观察员。
您可以尝试...
创建一个新表,例如:
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