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

时间:2015-01-22 15:48:04

标签: sql sql-server tsql stored-procedures

作为previous question关于storedproc_Task1调用storedproc_Task2的问题的后续跟进,我想知道SQL(SQL Server 2012)是否有办法检查proc是否为在调用它之前当前正在运行。

例如,如果storedproc_Task2storedproc_Task1都可以调用storedproc_Task3,我就不希望storedproc_Task1只调用storedproc_Task2 20 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)提出了问题,但更新了问题以使用storedproc_Task1之类的名称。根据{{​​3}}提醒,前缀sp_保留给[master]数据库中的系统过程。

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

鉴于希望任何进程调用sp_Task2等待sp_Task2完成如果它已经在运行,那么这实际上是sp_Task2单个螺纹的。

这可以通过使用应用程序锁来实现(请参阅sp_getapplocksp_releaseapplock)。 Application Locks允许您围绕任意概念创建锁。意思是,您可以将@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)无法被其他人调用{{1}在当前定义的路径之外(即席查询或不采取此预防措施的新流程)。

请查看我对您的初始问题的回答,即不使用存储过程名称的sp_Task2前缀而不需要返回值。

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