Dar*_*inH 9 t-sql sql-server sql-server-agent sql-agent-job
我目前正在使用这样的代码来检测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)
)
Run Code Online (Sandbox Code Playgroud)
那里没有问题,一般来说,它运作得很好.
但....(总是一个但是)
有时,我会调用它,取回"工作未运行"的结果,此时我会尝试通过以下方式启动工作
exec msdb.dbo.sp_start_job @JobName
Run Code Online (Sandbox Code Playgroud)
并且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
Run Code Online (Sandbox Code Playgroud)
不过这是问题所在.
10次中有9次,这很好用.SQL代理将引发错误,它被捕获,并且处理继续,因为作业已经运行,没有任何伤害没有犯规.
但偶尔,我会在"作业历史记录"视图中收到一条消息(请记住上面的代码,以检测特定作业是否正在运行,如果没有实际从另一个作业运行则启动它)说该作业失败,因为"SQLAgent已经拒绝开始工作,因为它已经有待处理的请求".
当然,这是TRY CATCH应该处理的确切错误!
当发生这种情况时,正在执行的工作就会消失,但不能立即从我所知道的情况开始,只是非常接近.我把日志记录到了所有地方并且没有一致性.有一次它失败了,它将在a处,a下一次在b处.在某些情况下,地方A和地方B只有一个
select @var = 'message'
Run Code Online (Sandbox Code Playgroud)
在他们之间.很奇怪.基本上,这项工作似乎是毫不客气地被抛弃的,而且在工作中要执行的任何事情都不会被执行.
但是,如果我删除"exec StartJob"(或者它只调用一次,当我知道目标作业还不能运行时),一切都运行良好,我在工作中的所有处理都会运行.
所有这一切背后的目的是让一个工作由于触发器(以及其他事情)而启动,并且,如果工作已经开始,则实际上没有必要"再次启动它".
有没有人遇到过SQL Agent的Job处理这样的行为?
编辑:当前的控制流程如下:
首先,您有机会了解服务经纪人吗?从你的描述来看,这似乎就是你真正想要的。
区别在于,您不是启动作业,而是将数据放入 SB 队列,SB 会异步调用您的处理过程,并完全回避已运行作业等的问题。它将自动生成/终止其他线程并根据需求指示,它负责顺序等。
这是一个很好的(并且模糊相关的)教程。http://www.sqlteam.com/article/centralized-asynchronous-auditing-with-service-broker
让我们假设您出于某种原因不能使用 SB(但说真的,可以!)。
使用作业 spid 的 context_info 怎么样?
包装器过程中的第一条语句是
DECLARE @context_info VARBINARY(30)
SET @context_info = CAST('MyJob1' AS VARBINARY)
SET CONTEXT_INFO @context_info
Run Code Online (Sandbox Code Playgroud)当你的过程完成时(或在你的 catch 块中)
SET CONTEXT_INFO 0x0
Run Code Online (Sandbox Code Playgroud)当您考虑给您的工作打电话时,请执行以下操作:
IF NOT EXISTS (SELECT * FROM master..sysprocesses WITH (NOLOCK) WHERE context_info=CAST('MyJob1' AS VARBINARY))
EXEC StartJob
Run Code Online (Sandbox Code Playgroud)当你的包装程序终止或连接关闭时,你的 context_info 就会消失。
您还可以使用全局临时表(即 ##JobStatus),当引用它的所有 spid 断开连接或显式删除它时,它们将消失。
只是一些想法。
归档时间: |
|
查看次数: |
22215 次 |
最近记录: |