我们有一个SQL Server 2005(SERVER-A)服务器,它为最近locking的应用程序保存数据库。 我们怀疑问题是事务锁,所以我们决定使用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导致锁? 如果是的话,我们该如何防范呢?
如果SERVER-A被指定为“链接服务器”,那么查询与链接数据有关的表将被传递给SERVER-A ,就好像它们是直接针对SERVER-A执行SERVER-A 。 因此,他们显然可能会造成锁。
在你的情况下,使用READ COMMITTED事务隔离级别,SELECT查询将在整个查询执行期间持有对受影响行(可能是整个表)的读锁,从而有效地防止在这些行上执行更新以及需要对整个表进行locking的语句(如DML语句)。
请注意,该声明似乎已经运行了一段时间(至less一分钟)。 如果您有更长时间的selectblockig更新,请考虑使用事务隔离级别SNAPSHOT或READ UNCOMMITTED来运行它们,具体取决于您的性能和数据一致性要求。 有关详细信息,请参阅有关事务隔离级别的文档 。
从我对本主题的有限理解中,隔离级别为“读取已提交”(如块报告中所示),SELECT语句将获取当前行上的共享锁,以防止在读取期间更新数据。
这有效地防止了INSERT事务获得对所述行的排他锁,所以是的,根据你的数据结构和索引locking级别选项 ,SELECT子句肯定会导致阻塞。
我不是超级SQL DBA,但是比我更聪明的人写了关于使用非聚集索引覆盖绕过锁的问题。 我发现这篇文章非常有教育意义