为什么SQL Server意外停止发出范围锁定

时间:2013-12-09 05:27:34

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

我对以下情况感到困惑:当访问表中超过一定数量的行时,范围锁的发布会令人惊讶地停止。

简要说明:有一个表具有唯一的聚簇索引;除了PK表不包含唯一列。我们尝试从这个表中选择所有可序列化的值(它不会发生可重复读取IL)隔离级别。一切都按预期进行(正如msdn所说:持有的RangeS-S锁的数量是n + 1,其中n是满足查询的行数。),直到超出一定数量的行限制。

我认为提供代码示例会更好:

if (exists (select * from information_schema.tables where table_name = 'T'))
    drop table T

create table T
(
    id int not null,
    val int not null
    primary key (id)
)

declare @numOfRow int = 10000 -- after 6232 range locks doesn't issued

begin tran
    declare @i int = 0
    while @i < @numOfRow 
    begin
        insert into T
        values (@i, @i)

        set @i = @i + 1
    end
commit

--set transaction isolation level repeatable read
set transaction isolation level serializable
begin tran
    select *
    from T -- with (holdlock)

    select *
    from sys.dm_tran_locks
    where request_session_id = @@SPID
commit

对我来说,如果我将@numOfRow设置为等于6233且更大,则不会发出范围锁定。

@@VERSION = Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (X64)   Jul  9 2008 14:17:44   Copyright (c) 1988-2008 Microsoft Corporation  Enterprise Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1) 

enter image description here

1 个答案:

答案 0 :(得分:2)

它确实获得了范围锁。

因为每个锁消耗内存lock escalation可以启动,但通常在获取5,000个锁之后的某个时刻启动。

锁定升级会导致较少粒度级别的锁定。

要查看此内容,您可以添加dbcc traceon(1200,3604,-1)

enter image description here

请记得使用dbcc traceoff(1200,3604,-1)

再次关闭标记