我目前正在使用这样的代码来检测SQL服务器作业是否正在运行。 (这是SQL Server 2005,所有SP的)
return (select isnull(
(select top 1 CASE
WHEN current_execution_status = 4 THEN 0
ELSE 1
END
from openquery(devtestvm, 'EXEC msdb.dbo.sp_help_job')
where current_execution_status = 4 and
name = 'WQCheckQueueJob' + cast(@Index as varchar(10))
), 1)
)
那里没有问题,一般来说,它运作得很好。
但....(总是一个但是)
有时候,我会调用它,取回“工作未运行”的结果,此时我会尝试通过
开始工作exec msdb.dbo.sp_start_job @JobName
并且SQL将返回“SQLAgent拒绝启动该作业,因为它已经有待处理的请求”。
确定。也不是问题。可以想象,在此代码启动之前,可以启动目标作业的一个小窗口,但在检查它是否已启动之后。但是,我可以将它包装在try catch中,然后忽略错误,对吧?
begin try
if dbo.WQIsQueueJobActive(@index) = 0 begin
exec msdb.dbo.sp_start_job @JobName
break
end
end try begin catch
-- nothing here
end catch
这是问题所在。
10次中有9次,这很好用。 SQL代理将引发错误,它被捕获,并且处理继续,因为作业已经运行,没有任何伤害没有犯规。
但偶尔,我会在“作业历史记录”视图中收到一条消息(请记住上面的代码,以检测特定作业是否正在运行,如果没有实际从另一个作业运行则启动它)说该作业失败,因为“SQLAgent拒绝启动这项工作,因为它已有待处理的请求”。
当然,这是TRY CATCH应该处理的确切错误!
当发生这种情况时,正在执行的工作就会消失,但不能立即从我所知道的情况开始,只是非常接近。我把日志记录到了所有地方并且没有一致性。有一次它失败了,它将在a处,a下一次在b处。在某些情况下,地点A和地方B只有
select @var = 'message'
在他们之间。很奇怪。基本上,这项工作似乎是毫不客气地被抛弃的,而且在工作中执行的任何事情都不会被执行。
但是,如果我删除“exec StartJob”(或者只调用一次,当我知道目标作业还不能运行时),一切都运行良好,我在工作中的所有处理都会运行。
所有这一切背后的目的是让一个工作因触发器(以及其他事情)而开始,如果工作已经开始,那么就没有必要“再次启动它”。
任何人都遇到过这样的行为,使用SQL Agent的作业处理?
编辑: 目前的控制流程如下:
答案 0 :(得分:4)
首先,你有没有机会看服务经纪人?根据您的描述,听起来就像您真正想要的那样。
不同之处在于,不是启动作业,而是将数据放入SB队列,SB将异步调用处理过程并完全解决已经运行的作业等问题。它将自动生成/终止其他线程和需求决定,它照顾秩序等。
这是一个很好的(和模糊的相关)教程。 http://www.sqlteam.com/article/centralized-asynchronous-auditing-with-service-broker
让我们假设您不能出于任何原因使用SB(但严重的是,做!)。
使用作业spid的context_info怎么样?
包装器proc中的第一个语句是
DECLARE @context_info VARBINARY(30)
SET @context_info = CAST('MyJob1' AS VARBINARY)
SET CONTEXT_INFO @context_info
当你的过程结束时(或在你的阻挡区中)
SET CONTEXT_INFO 0x0
当您正在考虑打电话时,请执行以下操作:
IF NOT EXISTS (SELECT * FROM master..sysprocesses WITH (NOLOCK) WHERE context_info=CAST('MyJob1' AS VARBINARY))
EXEC StartJob
当你的包装器proc终止或连接关闭时,你的context_info就会消失。
您还可以使用全局临时表(即## JobStatus)当引用它的所有spid断开连接或显式删除时,它们将消失。
只是一些想法。
答案 1 :(得分:2)
我有一个查询,它可以为我提供正在运行的工作,也许它可以帮到你。它一直在为我工作,但如果你发现它有任何错误,请告诉我,我会尽力纠正。欢呼声。
-- get the running jobs
--marcelo miorelli
-- 10-dec-2013
SELECT sj.name
,DATEDIFF(SECOND,aj.start_execution_date,GetDate()) AS Seconds
FROM msdb..sysjobactivity aj
JOIN msdb..sysjobs sj on sj.job_id = aj.job_id
WHERE aj.stop_execution_date IS NULL -- job hasn't stopped running
AND aj.start_execution_date IS NOT NULL -- job is currently running
--AND sj.name = 'JobName'
and not exists( -- make sure this is the most recent run
select 1
from msdb..sysjobactivity new
where new.job_id = aj.job_id
and new.start_execution_date > aj.start_execution_date )
答案 2 :(得分:-3)
处理已经运行的作业: 1.打开任务管理器 2.检查具有ImageName“DTExec.exe”的进程是否正在运行 3.如果进程正在运行且是否有问题,请执行“结束进程”。