远程查询会导致锁吗?

远程查询会导致锁吗?

我们有一台 SQL Server 2005 (SERVER-A) 服务器,它保存着一个应用程序的数据库,该应用程序最近经常被锁定。我们怀疑问题出在事务锁上,所以我们决定使用 SQL Server Profiler 在该服务器上捕获一些跟踪,我们开始捕获阻塞进程报告并得到了以下信息:

<blocked-process-report monitorLoop="3501256">
 <blocked-process>
  <process id="processffffffff83047a68" taskpriority="0" 
    logused="0" waitresource="OBJECT: 18:85575343:0 " waittime="27656" 
    ownerId="1540544048" transactionname="InsertCall" 
    lasttranstarted="2013-11-25T14:40:43.083" XDES="0x3790fad8" 
    lockMode="IX" schedulerid="2" kpid="6852" status="suspended" 
    spid="78" sbid="0" ecid="0" priority="0" transcount="2" 
    lastbatchstarted="2013-11-25T14:40:43.083" lastbatchcompleted="2013-11-25T14:40:43.073" 
    clientapp="" hostname="" hostpid="3256" loginname="" 
    isolationlevel="read committed (2)" xactid="1540544048" currentdb="18" 
    lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056">
   <executionStack>
    <frame line="201" stmtstart="10790" stmtend="11790" sqlhandle=""/>
    <frame line="1" sqlhandle=""/>
   </executionStack>
   <inputbuf>EXEC SomeProcedure</inputbuf>
  </process>
 </blocked-process>
 <blocking-process>
  <process status="suspended" waittime="15" spid="51" sbid="2" ecid="0" priority="0" 
  transcount="1" lastbatchstarted="2013-11-25T14:40:20.900" 
  lastbatchcompleted="2013-11-25T14:40:20.900" lastattention="2013-11-25T14:39:18.530" 
  clientapp="Microsoft SQL Server" hostname="SERVER-B" hostpid="1340" loginname="" 
  isolationlevel="read committed (2)" xactid="1540536548" currentdb="7" 
  lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
   <executionStack>
    <frame line="1" sqlhandle=""/>
    <frame line="1" sqlhandle=""/>
   </executionStack>
   <inputbuf>INCOMING SELECT FROM SERVER-B</inputbuf>
  </process>
 </blocking-process>
</blocked-process-report>

在 SERVER-B 上,有另一个 SQL Server 2008,它将 SERVER-A 作为链接服务器,并且它只执行远程 SELECT。所以我不明白之前的捕获,远程 select 会导致锁定吗?如果会,我们如何防止这种情况?

答案1

如果SERVER-A被指定为“链接服务器”,那么对与链接数据有关的表的查询将被传递到 ,SERVER-A就像它们是直接针对 执行的一样SERVER-A。因此,它们显然会导致锁定。

在您的情况下,使用 READ COMMITTED 事务隔离级别,SELECT 查询将在整个查询执行期间对受影响的行(可能是整个表)保持读锁,从而有效地阻止对这些行执行更新以及需要对整个表进行锁定的语句(例如 DML 语句)。

请注意,该语句似乎已经运行了一段时间(至少一分钟)。如果有此类长时间运行的选择阻止更新,请考虑使用事务隔离级别或来运行它们SNAPSHOTREAD UNCOMMITTED具体取决于您的性能和数据一致性要求。请参阅有关事务隔离级别的文档了解详情。

答案2

从我对这个主题的有限理解来看,如果隔离级别为“读取已提交”(如您的块报告中所示),SELECT 语句将获取当前行上的共享锁,以防止在读取期间更新数据。

这有效地阻止了 INSERT 事务获取该行的独占锁,所以是的,取决于你的数据结构和索引锁级别选项,SELECT 子句肯定会导致阻塞。

我不是超级 SQL DBA,但许多比我聪明的人都写过关于使用非聚集索引覆盖绕过锁的文章。我发现这篇特别的文章非常有教育意义

相关内容