【发布时间】:2020-12-18 07:51:38
【问题描述】:
我有一个可以安排工作的应用程序。我对作业的控制有限。该作业执行存储过程。有什么办法可以锁定存储过程,使作业不能同时执行这个存储过程? 我想检查一下 SQL server 是否提供了一些东西。
【问题讨论】:
标签: sql sql-server
我有一个可以安排工作的应用程序。我对作业的控制有限。该作业执行存储过程。有什么办法可以锁定存储过程,使作业不能同时执行这个存储过程? 我想检查一下 SQL server 是否提供了一些东西。
【问题讨论】:
标签: sql sql-server
您可以使用sp_getapplock 获取“自定义”或“应用程序”锁,并使用sp_releaseapplock 释放它。
辅助函数是:
请注意,sp_getapplock 不会锁定数据库中的任何表,它只会创建一个自定义命名锁。应用程序可以使用此功能来处理并发。
示例:
在 SSMS 中打开 2 个查询窗口,并在 1 分钟内运行以下代码。
DECLARE
@LockResult INT
, @LockErrorMessage NVARCHAR(MAX) = N'Failed to acquire lock.'
;
EXEC @LockResult = sys.sp_getapplock
@Resource = N'TestResource'
, @LockMode = N'Exclusive'
, @LockOwner = N'Session'
, @LockTimeout = 60000 /* 1 minute */
, @DbPrincipal = N'public'
;
IF (@LockResult < 0) BEGIN
THROW 50000, @LockErrorMessage, 0;
END
ELSE
BEGIN
SELECT 1 AS test;
/* EXEC MyControlledSP */
/* For demonstration purposes only! */
WAITFOR DELAY '00:02:00';
/* The work is done, release the lock */
EXEC sys.sp_releaseapplock
@Resource = N'TestResource'
, @LockOwner = N'Session'
, @DbPrincipal = N'public'
;
END;
您可以在 SP 本身中获取锁并仅在成功获取锁时运行它的主体,因此使用该存储过程的任何应用程序/进程也将隐式检查锁,您不会依赖于拥有所有应用程序/处理调整。
不要忘记释放锁,尤其是当所有者是会话时。关闭连接(例如关闭查询窗口)会自动释放锁。
如果计划任务是 SQL Server 代理作业,您不必执行自定义锁定,因为一个作业只能运行一次,并且当有正在运行的实例时,代理不会启动第二个(即使日程安排会这样说)。
【讨论】: