sql - 存储过程的应用程序锁
问题描述
我有一个安排工作的应用程序。我对作业的控制有限。该作业执行存储过程。有什么办法可以锁定存储过程,使作业不能同时执行这个存储过程?我想检查是否有 SQL 服务器提供的东西。
解决方案
您可以使用sp_getapplock来获取“自定义”或“应用程序”锁,并使用 sp_releaseapplock来释放它。
辅助函数是:
- APPLOCK_TEST - 返回有关是否可以在特定应用程序资源上授予锁定的信息
- APPLOCK_MODE - 此函数返回锁定所有者在特定应用程序资源上持有的锁定模式
请注意,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 代理作业,则不必进行自定义锁定,因为一个作业只能运行一次,并且当有一个正在运行的实例时,代理不会启动第二个(即使调度会这样说的)。
推荐阅读
- python-3.x - Contructing new dataframe and keeping old one?
- java - Creating a 2D Array and filling the array with random numbers
- python - What's the best way to modify a variable using a function, but inside of another function?
- ios - ios/index/DataStore 的使用
- laravel - laravel 保持表单数据在按下按钮后不刷新
- apache-spark - 如果 RDD 变大,Spark 将如何反应?
- c++ - Simple Noob C++ Input/Output Question: Code Error
- r - Multiply column by every other column
- android - longClick 上的振动/声音反馈
- r - 无法在 R 中安装 devtools