SQL Server 读锁定行为

SQL Server 读锁定行为

当 SQL Server 联机丛书提到“资源上的共享 (S) 锁已释放读取操作完成后,除非将事务隔离级别设置为可重复读或更高,或者使用锁定提示在事务持续期间保留共享(S)锁。”

假设我们谈论的是行级锁,没有显式事务,在默认隔离级别(读已提交),那么“读操作“ 指 什么?

  • 读取单行数据?
  • 单个 8k IO Page 的读取?
  • 或者直到创建锁的完整 Select 语句完成执行,无论涉及多少其他行?

注意:我需要知道这一点的原因是,我们有一个由数据层 Web 服务生成的几秒钟的只读 select 语句,该语句会创建页面级共享读取锁,由于与来自保持服务器更新的复制过程的行级独占更新锁相冲突而产生死锁。select 语句相当大,有许多子选择,一位 DBA 建议我们重写它以将其分解为多个较小的语句(较短的运行片段),“以减少锁定的时间”。因为这假设共享读取锁会一直保持到整个 select 语句完成,如果这是错误的(如果在读取行或页面时释放锁),那么这种方法将没有任何效果……

答案1

不幸的是,这种行为相当复杂,而且没有公开记录。这取决于正在执行的语句,有些执行计划将使用一种锁获取/释放策略,而其他执行计划将使用另一种策略。但一般来说,S 锁和 IS 锁的持有时间很短,在语句执行期间,S 锁的获取和释放速度可能相当快。只有在可重复读取和可序列化读取隔离级别下,共享锁才会长时间持有(在事务持续期间)。

最好的调查工具是 Profiler,因为锁定:已获得锁定:已释放事件被追踪,包含所有需要的详细信息。事件也可以使用,但是使用起来有点棘手。

但是,如果锁争用是一个问题,一个简单的解决方案是启用读取已提交快照隔离。启用此功能后,读取已提交的读取不再获取任何锁,而是从 tempdb 中的版本存储中获取锁定的数据。当然,缺点是需要维护版本存储,这会增加 tempdb 的工作负载。

答案2

“因为这假设共享读锁被保持直到整个 select 语句完成”

该文档页面的第一行写道:“Microsoft® SQL Server™ 2000 具有多粒度锁定,允许事务锁定不同类型的资源。”(http://msdn.microsoft.com/en-us/library/aa213039%28SQL.80%29.aspx

因此资源似乎被事务锁定 - 包含各种子查询的大型选择查询将是一个事务。

另外,人们会认为 select 语句会同时锁定所有涉及的对象,因此可以进行可靠的时间点读取。

答案3

这意味着可以在语句或事务完成之前释放锁。

相关内容