sql-server - 为什么 SQL Server 意外停止发出范围锁

标签 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

最佳答案

它确实获取范围锁。

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

锁升级会导致粒度级别较低的锁数量减少。

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

enter image description here

记住使用dbcc traceoff(1200,3604,-1)再次关闭标志

关于sql-server - 为什么 SQL Server 意外停止发出范围锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20463762/

相关文章:

sql - 即使数据存在于 vb.net 中的 SqlDataReader 中,也无法尝试读取数据

sql - 在表中动态创建列

sql - 使用多个 WITH tablename AS (...) 语句 SQL Server

c - 带有 C : Passive RMA synchronization 的 MPI

sql - 如何判断触发器代码是否正在复制订阅服务器上执行?

sql-server - 在 SQL Server 2008 中获取新插入行的主键

sql-server - 按比例在帐户之间拆分 SQL 2008

sql-server-2008 - 投标 - SSIS - 错误时重定向行发送太多行

python - 使用 atexit 终止线程时脚本卡在退出处

java - 如何在 Java 中避免在保存到数据库之前同时处理唯一组合?