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