这是我在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取消了存储过程的执行,那么IsRunning
中的RunningProcesses
值永远不会更新回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
关键字退出存储过程。如果这不是一个好主意,那么解决这个问题的最佳方法是什么。
答案 0 :(得分:2)
使用内置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