0

我试图弄清楚如果有一个给定名称的锁,如何查询 SQL Server,也就是有一个锁。

这是正确的,因为它似乎过于复杂?

跑步

begin tran

print 'APPLOCK_TEST=' + convert(varchar(max), APPLOCK_TEST('public', 'testlock', 'Exclusive', 'Session'))
print 'APPLOCK_MODE=' + APPLOCK_MODE('public', 'testlock', 'Session')

declare @lock int
exec @lock = sp_getapplock @Resource = 'testlock', @Lockmode = 'Exclusive', @LockOwner = 'Session'
print(@lock)

print 'APPLOCK_TEST=' + convert(varchar(max), APPLOCK_TEST('public', 'testlock', 'Exclusive', 'Session'))
print 'APPLOCK_MODE=' + APPLOCK_MODE('public', 'testlock', 'Session')

返回

APPLOCK_TEST=1
APPLOCK_MODE=NoLock
0
APPLOCK_TEST=1
APPLOCK_MODE=Exclusive

在另一个选项卡中运行它:

begin tran

  print 'APPLOCK_TEST=' + convert(varchar(max), APPLOCK_TEST('public', 'testlock', 'Exclusive', 'Session'))
  print 'APPLOCK_MODE=' + APPLOCK_MODE('public', 'testlock', 'Session')

返回

APPLOCK_TEST=0
APPLOCK_MODE=NoLock

那么检查是否持有锁的方法是什么?

进行这种检查似乎是一种奇怪的方式。

//APPLOCK_TEST remains 1 when the session is the session who has the lock
//otherwise this is 0
//APPLOCK_MODE is "NoLock" when a different session has the lock
//otherwise if its the same then APPLOCK_MODE = "Exclusive" 
if(APPLOCK_TEST == 0 or APPLOCK_MODE != 'NoLock')
{
   //there currently is a lock
}
else
{
   //there is no lock.
}

我一直在看

https://www.mssqltips.com/sqlservertip/3202/prevent-multiple-users-from-running-the-same-sql-server-stored-procedure-at-the-same-time/ https://github。 com/madelson/DistributedLock/blob/5bd69af3f151710825f43ea1379a619a1b63ca1a/DistributedLock.SqlServer/SqlApplicationLock.cs#L164 https://www.endyourif.com/preventing-race-conditions-with-sp_getapplock/

和更多..

无论使用何种连接,请协助 SQL Server 检查当前是否存在锁。

4

1 回答 1

1

会话锁所有者不是事务范围的,因此事务是多余的。

使用APPLOCK_TESTand APPLOCK_MODE,下面的 T-SQL 将确定排他锁是否由任何会话持有,包括当前会话:

PRINT
    CASE WHEN 
        APPLOCK_TEST('public', 'testlock', 'Exclusive', 'Session') = 0 --held by other session and cannot be granted
        OR APPLOCK_MODE('public', 'testlock', 'Session') = 'Exclusive' --this session already holds Exclusive lock
        THEN 'Lock currently exists'
        ELSE 'No lock currently exists'
    END;

或者,您可以仅评估APPLOCK_MODE(以避免增加当前会话的锁引用计数),然后以零超时获取锁(以识别它由其他会话持有而不是阻塞)。如果您的意图是立即获取排他锁并且永不阻塞,我建议使用这种方法。

DECLARE @lock int = 0;
IF APPLOCK_MODE('public', 'testlock', 'Session') <> 'Exclusive' --this session does not already hold Exclusive lock
BEGIN
    EXEC @lock = sp_getapplock @Resource = 'testlock', @Lockmode = 'Exclusive', @LockOwner = 'Session', @LockTimeout = 0;
    PRINT
        CASE @lock
            WHEN    0 THEN 'lock was successfully granted synchronously.'
            WHEN    1 THEN 'The lock was granted successfully after waiting for other incompatible locks to be released.'
            WHEN   -1 THEN 'The lock request timed out.'
            WHEN   -2 THEN 'The lock request was canceled.'
            WHEN   -3 THEN 'The lock request was chosen as a deadlock victim.'
            WHEN -999 THEN 'Indicates a parameter validation or other call error.'
        END;
END
ELSE
BEGIN
    PRINT 'Current session already has Exclusive lock';
END;

;

于 2021-10-27T10:52:56.600 回答