【问题标题】:SQL Server : distributed locks how to checkSQL Server:分布式锁如何检查
【发布时间】:2021-12-12 12:26:25
【问题描述】:

我试图弄清楚如果有一个给定名称的锁,如何查询 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 检查当前是否存在锁,无论使用何种连接。

【问题讨论】:

  • 你还没有提交第一个查询的事务,你期望什么?
  • @Charlieface 请给我看代码,我试试看,结果完全一样......这也是我想的那样,但我想我会检查......
  • COMMIT TRAN; 在第一个脚本的末尾,在运行第二个脚本之前
  • 我认为您的问题是如何确定当前会话是否已经对指定资源具有相同的锁定。带有会话锁的事务是多余的。
  • @Charlieface 就像我说的那样不会改变结果......

标签: sql-server locking distributed-lock


【解决方案1】:

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

使用APPLOCK_TESTAPPLOCK_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;

;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-19
    • 2012-08-14
    • 2020-06-12
    • 2019-07-29
    相关资源
    最近更新 更多