【问题标题】:SQL Server: how to acquire exclusive lock to prevent race condition?SQL Server:如何获取排他锁以防止竞争条件?
【发布时间】:2011-03-17 16:25:40
【问题描述】:

我有以下 T-SQL 代码:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION T1_Test

    /*This is a dummy table used for "locking" 
    and it doesn't contain any meaningful data.*/        
    UPDATE lockTable 
        SET ID = 1    
        WHERE ID = 1

    DECLARE @Count TINYINT 

    SELECT @Count = COUNT(*)
    FROM debugSP 

    WAITFOR DELAY '00:00:5';

    INSERT INTO debugSP 
        (DateCreated, ClientId, Result)
    SELECT 
        GETDATE(), @@SPID, @Count

COMMIT TRANSACTION T1_Test

我正在使用带有注释的“锁定”hack 来获取排他锁。

注意:使用 TABLOCKX 或 UPDLOCK 提示将不起作用,因为我通过拆分语句并在中间添加 WAITFOR 命令以进行测试,从而破坏了 ATOMIC-ity。 我不想要这样的东西:

INSERT INTO debugSP (DateCreated, ClientId, Result)
SELECT GETDATE(), @@SPID, COUNT(*) 
FROM debugSP

这是同时运行两个会话(带锁表)后的正确结果

Id DateCreated           ClientId Result
-- ----------------------- -------- ------
 1 2011-03-17 15:52:12.287       66      0
 2 2011-03-17 15:52:24.534       68      1

那是运行带有注释掉锁的代码的错误结果

Id DateCreated           ClientId Result
-- ----------------------- -------- ------
 1 2011-03-17 15:52:43.128       66      0
 2 2011-03-17 15:52:46.341       68      0

有没有更好的方法来获取事务范围的独占锁而无需此类黑客攻击?

【问题讨论】:

标签: sql sql-server transactions locking isolation-level


【解决方案1】:

我不确定您要从发布的代码中执行什么操作。我想你只是想序列化对那段代码的访问?如果是这样,sp_getapplock 应该做你需要做的事情,而不是创建一个新的虚拟表来用于锁定。

Details here

【讨论】:

    【解决方案2】:

    您可以在具有可重复读取隔离的事务范围内使用锁定提示 WITH(XLOCK, ROWLOCK)。在可序列化隔离中,默认情况下会在读取操作上获得排他锁,因此如果您需要特定事务以并行运行,您可以在创建该事务时为该事务指定增加的序列化级别(您正在这样做;这是不是黑客,只是根据情况做事的方式)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-15
      • 1970-01-01
      • 2016-03-21
      • 2019-02-23
      相关资源
      最近更新 更多