当SQL Server联机丛书在线说“ 只要读取操作完成 , 就释放资源上的”共享(S)锁“,除非事务隔离级别设置为可重复读取或更高级别,或者使用locking提示来保留共享S)在交易期间locking。“
假设我们正在谈论行级锁,没有明确的事务,在默认隔离级别(Read Committed)下,“ 读操作 ”是指什么?
注:我需要知道的原因是我们有一个由数据层Web服务生成的几秒钟只读select语句,它创build页面级共享读取锁,由于与行级独占更新锁冲突而产生死锁从保持服务器更新的复制过程。 select语句相当大,有许多子select,一个DBAbuild议我们重写它,把它分解成多个较小的语句(较短的运行段),以“减less锁保持多久”。 因为这里假定共享读锁持续到完整的select语句结束,如果这是错误的(如果在行或页面被读取时锁被释放)那么这种方法将不会产生任何效果….
不幸的是,这种行为相当复杂,没有公开logging。 这取决于正在执行的语句,有些执行计划将使用一个锁获取/释放策略,另外一个将使用另一个。 但作为一般规则,S和IS锁持有很短的时间,在执行语句的过程中,S锁可能以相当疯狂的速度被获取和释放。 只有在可重复读取和可search的读取隔离级别下,共享锁保持很长时间(在事务期间)。
你最好的调查工具是Profiler,因为Lock:Acquired和Lock:Released events跟踪了所有需要的细节。 也可以使用XEvents ,但是要让它们继续下去会有点棘手。
但是,如果locking争用是一个问题,一个简单的解决scheme是启用读取提交的快照隔离。 当这个被打开的时候,读取提交读取不再获得任何locking,并从tempdb的版本存储获取locking的数据。 当然,缺点是需要维护版本存储,并将工作量增加到tempdb。
“因为这假定共享读锁持续到完整的select语句结束”
该文档页面的第一行说:“Microsoft®SQL Server™2000具有多粒度locking,允许不同types的资源被事务locking”。 ( http://msdn.microsoft.com/en-us/library/aa213039%28SQL.80%29.aspx )
所以资源似乎被事务locking – 你的大型select查询与各种子查询将是一个事务。
另外,人们会认为select语句会一次locking所有涉及的对象,因此可以进行可靠的时间点读取。
这意味着锁可以在声明或交易完成之前被释放。