代码之家  ›  专栏  ›  技术社区  ›  Charles Bretana

何时释放共享读取锁?

  •  10
  • Charles Bretana  · 技术社区  · 15 年前

    当SQLServer联机丛书说 “资源上的共享锁已释放 一旦读取操作完成 ,除非事务隔离级别设置为可重复读取或更高,或者使用锁定提示在事务期间保留共享锁。“

    假设我们讨论的是一个行级锁,在默认隔离级别(readcommitted)下没有显式事务,那么它的作用是什么呢?” 读操作 “指什么?

    • 读取一行数据?
    • 单个8k IO页面的读取?
    • 或者直到创建锁的完整Select语句完成执行为止,不管还有多少行

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

    3 回复  |  直到 15 年前
        1
  •  4
  •   ahains    15 年前

    实际上,这很有趣,您可能想启动profiler并跟踪一些简单查询的锁获取/释放。我做过这件事,有点像: 获取第1行 获取第2行 释放第1行 获取第3行 释放第2行 获取第2页 发布第1页 ...

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

        2
  •  1
  •   sjngm quinti    13 年前

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

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

    因此,我认为正在发生的是:

    1. 获取:db共享锁、表共享锁、页共享锁
    2. 页面已阅读。。。同时释放第页上的锁并在下一页获取锁

    两种情况的结果是,有时在sys.dm_tran_lock查询中。我看到两个页面锁,有时是一个,有时是三个。。取决于在同步操作过程中发生的更快。

        3
  •  0
  •   Ronnie Overby    6 年前

    关于具体文件,我发现:

    数据库引擎使用共享锁来防止其他事务 在当前事务运行读取时修改行 活动共享锁还阻止语句读取行 完整的。 共享锁类型决定何时释放它。 在读取下一页时释放,并释放表锁 当陈述结束时。

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