sql-server – 查明存储过程是否已在运行

这是我在SQL Server 2012中运行的存储过程.

ALTER PROCEDURE usp_ProcessCustomers
AS
BEGIN
    IF EXISTS (SELECT 1 FROM RunningProcesses WHERE ProcessId = 1 AND IsRunning = 1)
       RETURN;

    UPDATE RunningProcesses 
    SET IsRunning = 1 
    WHERE ProcessId = 1

-- Do processing here
-- Do processing here

UPDATE RunningProcesses 
    SET IsRunning = 0 
    WHERE ProcessId = 1
END
GO

可以从应用程序中的多个位置触发此存储过程.如果需要,甚至DBA也可以使用SSMS触发存储过程.

到现在为止还挺好.

问题是如果出现问题或者DBA取消了存储过程的执行,那么RunningProcesses中的IsRunning值永远不会更新回0.因此系统总是认为存储过程正在运行,即使它没有.

我在网上找到了以下脚本,用于检查脚本是否正在运行.

SELECT 
    r.*, t.text 
FROM 
    sys.dm_exec_requests r 
CROSS APPLY
    sys.dm_exec_sql_text(r.sql_handle) t
WHERE 
    r.status IN (N'Suspended', N'Running', N'Runnable', N'Pending')

使用上面的脚本来确定存储过程是否已经运行是一种好方法吗?如果它已经运行,那么我将使用RETURN关键字退出存储过程.如果这不是一个好主意,那么解决这个问题的最佳方法是什么.

最佳答案 使用内置的
application locks.如果会话或服务器意外关闭,SQL Server将确保释放锁.

ALTER PROCEDURE usp_ProcessCustomers
AS
BEGIN
    BEGIN TRANSACTION

    declare @Lock int
    EXEC @Lock = sp_getapplock @Resource = 'ProcessCustomers',
                               @LockMode = 'Exclusive'
    IF (@Lock < 0)  -- already locked by another process
       RETURN;

-- Do processing here
-- Do processing here

    EXEC sp_releaseapplock @Resource = 'ProcessCustomers'

    COMMIT TRANSACTION
END
点赞