如何在调用时检查 proc 是否已经 运行?

How to check if a proc is already running when called?

作为我的 的跟进,我询问 storedproc_Task1 调用 storedproc_Task2,我想知道是否 SQL (SQL Server 2012 ) 有一种方法可以在调用它之前检查一个过程当前是否 运行。

比如storedproc_Task2可以被storedproc_Task1storedproc_Task3调用,我不希望storedproc_Task1只调用storedproc_Task220 storedproc_Task3 秒后。我希望代码如下所示:

declare @MyRetCode_Recd_In_Task1 int
if storedproc_Task2 is running then
    --wait for storedproc_Task2 to finish
else 
    execute @MyRetCode_Recd_In_Task1 = storedproc_Task2 (with calling parameters if any).
end

问题是如何处理 if storedproc_Task2 is running 布尔值检查?

更新: 我最初使用存储过程的通用名称提出问题(即 sp_Task1),但已将问题更新为使用 [=12 这样的名称=] 代替。根据 srutzky 的提醒,前缀 sp_ 是为 [master] 数据库中的系统进程保留的。

如果您使用的是全局 table,如您在上一个问题的答案中所述,则只需在程序结束时删除全局 table,然后检查程序是否仍在运行运行 只需检查 table:

是否存在
If Object_ID('tempdb...##temptable') is null then -- Procedure is not running
--do something
else
--do something else
end

鉴于希望让任何调用 sp_Task2 的进程等到 sp_Task2 完成 如果它已经 运行,即本质上使 sp_Task2 成为单线程。

这可以通过使用应用程序锁来实现(请参阅 sp_getapplock and sp_releaseapplock)。应用程序锁让您可以围绕任意概念创建锁。意思是,您可以将 @Resource 定义为 "Task2",这将强制每个呼叫者等待轮到他们。它将遵循以下结构:

    BEGIN TRANSACTION;
    EXEC sp_getapplock @Resource = 'Task2', @LockMode = 'Exclusive';

    ...single-threaded code...

    EXEC sp_releaseapplock @Resource = 'Task2';
    COMMIT TRANSACTION;

您需要自己管理错误/ROLLBACK(如链接的 MSDN 文档中所述),因此放入通常的 TRY/CATCH。但是,这确实允许您管理情况。

这段代码可以放在sp_Task2的开头和结尾,如下:

CREATE PROCEDURE dbo.Task2
AS
SET NOCOUNT ON;

BEGIN TRANSACTION;
EXEC sp_getapplock @Resource = 'Task2', @LockMode = 'Exclusive';

{current logic for Task2 proc}

EXEC sp_releaseapplock @Resource = 'Task2';
COMMIT TRANSACTION;

也可以放在所有调用sp_Task2的位置,如下:

CREATE PROCEDURE dbo.Task1
AS
SET NOCOUNT ON;

BEGIN TRANSACTION;
EXEC sp_getapplock @Resource = 'Task2', @LockMode = 'Exclusive';

EXEC dbo.Task2 (with calling parameters if any);

EXEC sp_releaseapplock @Resource = 'Task2';
COMMIT TRANSACTION;

我认为第一个选择——将逻辑放在 sp_Task2 中——将是最干净的,因为 a) 它位于一个位置并且 b) 其他人调用 sp_Task2 在当前定义的路径之外(临时查询或不采取此预防措施的新过程)。

关于不使用 sp_ 前缀作为存储过程名称并且不需要 return 值,请参阅我对您最初问题的回答。

请注意: sp_getapplock / sp_releaseapplock 应谨慎使用;应用程序锁肯定非常方便(例如在这种情况下),但只有在绝对必要时才应使用它们。