11

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

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

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

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

4

3 回答 3

4

实际上观看非常有趣,您可能想要启动分析器并跟踪一些简单查询的锁定获取/释放。我前一阵子这样做了,它类似于:获取第 1 页获取第 1 行获取第 2 行发布第 1 行获取第 3 行发布第 2 获取第 2 页发布第 1...

我可能不是 100% 正确,但这基本上是方法。因此,在读取行之后释放锁,或者更准确地说,它是在获取下一行锁之后。我怀疑这可能与保持一致的遍历状态有关。

于 2009-06-02T21:15:27.577 回答
1

我不相信它会同时获得两个页面级锁。我认为它只以这种方式出现在分析器中,因为事件发生得如此之快。如果它像您怀疑的那样发生,总会有两个页面级锁,但是当运行一个带有共享锁的大型查询时,我有时会看到两个页面级锁,有时会通过这个查询看到一个:

SELECT *
FROM sys.dm_tran_locks
WHERE request_session_id = <SPID>

所以,我认为正在发生的是:

  1. 获取:db共享锁、表共享锁、页共享锁
  2. 页面被读取...同时在页面上释放锁定并在下一页获取锁定

两者的结果是有时在 sys.dm_tran_lock 查询中。我看到两个 PAGE 锁,有时是一个和几次三个 .. 取决于同时操作期间发生的更快。

于 2012-01-13T07:47:13.857 回答
0

关于具体文档,我发现了这一点:

如果 READ_COMMITTED_SNAPSHOT 设置为 OFF(SQL Server 上的默认设置),则数据库引擎使用共享锁来防止其他事务在当前事务正在运行读取操作时修改行。共享锁还阻止语句读取其他事务修改的行,直到其他事务完成。共享锁类型决定何时释放。在处理下一行之前释放行锁。读取下一页时释放页锁,语句完成时释放表锁。

来源:https ://docs.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-2017

于 2019-01-07T17:09:58.270 回答