Sql Server忽略rowlock提示

时间:2011-12-04 10:45:04

标签: sql-server locking serializable

这是关于如何在表中不存在时锁定值范围(以及其他任何内容!)的一般问题。这个问题的触发器是我想要“插入如果不存在”,我不想使用MERGE,因为我需要支持SQL Server 2005。

在第一个连接中我:

  1. begin transaction
  2. 使用(SERIALIZABLE, ROWLOCK) + where子句从表中选择数据以重新指定范围
  3. 等待...
  4. 在第二个连接中,我将数据插入到表中,其值匹配第一个连接中的where子句

    我希望第二个连接不受第一个连接的影响,但只有在我提交(或回滚)第一个连接的事务后才会完成。

    我错过了什么?

    这是我的测试代码:

    首先创建此表:

    CREATE TABLE test
    (
        VALUE nvarchar(100)
    )
    

    其次,打开新的查询窗口sql server managements studio并执行以下命令:

    BEGIN TRANSACTION;
    SELECT *
    FROM  test WITH (SERIALIZABLE,ROWLOCK)
    WHERE value = N'a';
    

    第三步,打开另一个新的查询窗口并执行以下命令:

    INSERT INTO test VALUES (N'b');
    

    请注意,在第一个窗口中的事务结束之前,第二个查询不会结束

1 个答案:

答案 0 :(得分:8)

您缺少VALUE上的索引。

如果没有SQL Server没有任何内容可以使用key range lock并且将锁定整个表以锁定范围。

即使添加了索引,您仍会遇到问题中的方案阻塞。 RangeS-S锁定不会锁定查询中指定的特定范围。相反,它会锁定所选范围任一侧的键之间的范围。

当任何一侧没有这样的键时,范围锁会延伸到无穷大。您需要在ab之间添加一个值(例如aa),以防止在您的测试中发生这种情况并阻止插入b

有关此内容的详情,请参阅本文中的Bonus Appendix: Range Locks