什么时候发布共享读锁?

时间:2009-06-02 21:07:33

标签: sql-server locking isolation-level

当SQL Server Books在线时说 “一旦读取操作完成 ,资源上的共享(S)锁就会被释放 ,除非事务隔离级别设置为可重复读取或更高,或者是锁定提示用于在事务期间保留共享(S)锁。“

假设我们在默认隔离级别(Read Committed)上讨论的是没有显式事务的行级锁定,那么“ 读取操作 ”会引用什么至?

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

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

3 个答案:

答案 0 :(得分:4)

实际观察非常有趣,你可能想要启动探查器并跟踪一些简单查询的锁定获取/释放。我做了一段时间回来,它是这样的: 获取第1页 获得第1行 获得第2行 发布第1行 获得第3行 发布第2行 获取第2页 发布第1页 ...

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

答案 1 :(得分:1)

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

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

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

  1. 获取:db共享锁,表共享锁,页共享锁
  2. 页面被读取...页面上的同时发布锁定并在下一页获取锁定
  3. 两个结果是有时在sys.dm_tran_lock查询中。我看到两个PAGE锁定,有时一次和几次三次......取决于同时操作期间发生的更快。

答案 2 :(得分: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