sql-server – SQL Server 2008 R2中的死锁问题(.Net 2.0应用程序)

前端之家收集整理的这篇文章主要介绍了sql-server – SQL Server 2008 R2中的死锁问题(.Net 2.0应用程序)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
有问题的sql Server 2008 R2实例是一个重负载OLTP生产服务器.几天前出现了死锁问题,但仍未得到解决.我们收到了Xml死锁报告,其中列出了死锁中涉及的存储过程以及其他一些细节.我将首先尝试从这个xml中列出事实:

死锁涉及两个存储过程,例如SP1和SP2.根据报告,SP1在隔离级别“Serializable”中运行,SP2在“ReadCommitted”中运行.

我们调查了以下内容

>我们是否设置了IsolationLevel SP1
SP内部或“内部”中的“可序列化”
码? – 没有.
>是否有其他SP的IsolationLevel
是“Serializable”调用SP1? – 没有.
> SP1使用的表是否被调用
任何其他具有隔离功能的SP
级别为“可序列化”? – 是的
有些SP具有隔离功能
级别设置为“可序列化”和
访问与SP1相同的表,
但我们不知道他们是否
当时正在运行
僵局与否是僵局
报告仅显示SP1和SP2.

思路:
我们考虑了以下可能的原因:

>发生了死锁,因为SP1是
以“Serializable”运行. – 为什么是
此SP在Serializable中运行时
我还没设置好吗?是隔离
等级升级(像锁一样)?如果
我们想出来,让它运行
ReadCommitted,问题是什么
解决
>任何其他SP正在运行,锁定
SP1使用的表并导致a
SP1和SP2之间的死锁. –
这个SP不会被列入
死锁报告?可以僵局
报告错过这样的依赖?如是
那么我们可能只会偏袒
信息.这仍然没有
解决SP1的运行方式
但是可序列化.

建议:

>如果此信息不充分
解决问题时,我该怎么办?
sql获取更多信息
服务器为我的目的和什么
我应该尝试收集哪些信息?
>你想要的任何其他思路
追求解决这个问题?

更新:
这是死锁的跟踪日志信息.我已经更改了SP等的名称,但已经检查并验证了更改不会遗漏任何相关信息.检查代码后面的注释,了解有关表等的更多信息.

?<EVENT_INSTANCE>
  <EventType>DEADLOCK_GRAPH</EventType>
  <PostTime>2010-09-07T11:27:47.870</PostTime>
  <SPID>16</SPID>
  <TextData>
    <deadlock-list>
      <deadlock victim="process5827708">
        <process-list>
          <process id="process5827708" taskpriority="0" logused="0" waitresource="KEY: 7:72057594228441088 (8d008a861f4f)"
                   waittime="5190" ownerId="1661518243" transactionname="SELECT" lasttranstarted="2010-09-07T11:27:42.657"
                   XDES="0x80bf3b50" lockMode="RangeS-S" schedulerid="4" kpid="2228" status="suspended" spid="76" sbid="0"
                   ecid="0" priority="0" trancount="0" lastbatchstarted="2010-09-07T11:27:42.657"
                   lastbatchcompleted="2010-09-07T11:27:42.657" clientapp=".Net sqlClient Data Provider"
                   hostname="xxx" hostpid="5988" loginname="xxx" isolationlevel="serializable (4)"
                   xactid="1661518243" currentdb="7" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056">
            <executionStack>
              <frame procname="SP1" line="12" stmtstart="450" stmtend="6536"
                     sqlhandle="0x0300070090cbdc7742720c00e99d00000100000000000000">
                Select ... from Table1,Table2,Table4,Table5
              </frame>
            </executionStack>
            <inputbuf>
              Proc [Database Id = 7 Object Id = 2010958736]
            </inputbuf>
          </process>
          <process id="process5844bc8" taskpriority="0" logused="1873648" waitresource="KEY: 7:72057594228441088 (0e00ce038ed0)"
                   waittime="4514" ownerId="1661509575" transactionname="user_transaction" lasttranstarted="2010-09-07T11:27:40.423"
                   XDES="0x37979ae90" lockMode="X" schedulerid="7" kpid="3260" status="suspended" spid="104" sbid="0" ecid="0"
                   priority="0" trancount="2" lastbatchstarted="2010-09-07T11:27:43.350" lastbatchcompleted="2010-09-07T11:27:43.350"
                   clientapp=".Net sqlClient Data Provider" hostname="xxx" hostpid="5988" loginname="xxx"
                   isolationlevel="read committed (2)" xactid="1661509575" currentdb="7" lockTimeout="4294967295"
                   clientoption1="673185824" clientoption2="128056">
            <executionStack>
              <frame procname="SP2" line="68" stmtstart="5272" stmtend="5598"
                     sqlhandle="0x030007003432350f109a0c00e99d00000100000000000000">
                UPDATE Table1 ...
              </frame>
            </executionStack>
            <inputbuf>
              Proc [Database Id = 7 Object Id = 255144500]
            </inputbuf>
          </process>
        </process-list>
        <resource-list>
          <keylock hobtid="72057594228441088" dbid="7" objectname="Table1" indexname="Index1"
                   id="lock448e2c580" mode="X" associatedObjectId="72057594228441088">
            <owner-list>
              <owner id="process5844bc8" mode="X" />
            </owner-list>
            <waiter-list>
              <waiter id="process5827708" mode="RangeS-S" requestType="wait" />
            </waiter-list>
          </keylock>
          <keylock hobtid="72057594228441088" dbid="7" objectname="Table1" indexname="Index1"
                   id="lock2ba335880" mode="RangeS-S" associatedObjectId="72057594228441088">
            <owner-list>
              <owner id="process5827708" mode="RangeS-S" />
            </owner-list>
            <waiter-list>
              <waiter id="process5844bc8" mode="X" requestType="wait" />
            </waiter-list>
          </keylock>
        </resource-list>
      </deadlock>
    </deadlock-list>
  </TextData>
  <TransactionID />
  <LoginName>xx</LoginName>
  <StartTime>2010-09-07T11:27:47.867</StartTime>
  <ServerName>xxx</ServerName>
  <LoginSid>xxx</LoginSid>
  <EventSequence>116538375</EventSequence>
  <IsSystem>1</IsSystem>
  <SessionLoginName />
</EVENT_INSTANCE>

SP1正在执行一个select,它从5个不同的表(Table1到Table5)获取数据(使用内部查询等).SP2对Table1执行更新.
有趣的是,SP2更新的一列是Table1中的外键字段和Table2的主键,而Table1和Table2都是SP1的select语句的一部分,不确定这是否相关但不想错过任何东西.

注意:indexname =“Index1”(在上面的死锁图中) – Index1与Table1中的外键和Table2的主键位于同一列上.

解决方法

检查这个 MSDN article,其中说明:

An isolation level has connection-wide scope,and once set for a
connection with the SET TRANSACTION ISOLATION LEVEL statement,it
remains in effect until the connection is closed or another isolation
level is set. When a connection is closed and returned to the pool,
the isolation level from the last SET TRANSACTION ISOLATION LEVEL
statement is retained. Subsequent connections reusing a pooled
connection use the isolation level that was in effect at the time the
connection is pooled.

问题是连接以Serializable隔离级别打开;关联的事务已被处置,连接也是如此,但连接没有被销毁并进入连接池.下次发出连接请求(使用相同的连接字符串)时,会返回此连接,并且由于查询未指定任何隔离级别,因此它在Serializable隔离级别中执行.

基本上,如果你有一个连接池并在一个特定的隔离级别打开一个连接,让我们说Serializable,那么连接将返回到池,隔离级别设置为Serializable.下次请求连接时,您无法确定是否不会返回此连接,因此即使通过默认隔离级别进行ReadCommitted,您也可能会获得这些“Serializable”连接之一.

另一个需要注意的是,每次将隔离级别设置为Serializable(或其他任何内容)时,您可能会选择不同的连接,并且通过将其隔离级别设置为Serializable(或其他任何内容),您可能会慢慢污染连接池中的越来越多的连接.你设定).

我没有找到任何重置处置连接的机制(当它在执行我的查询后回到连接池时).一种解决方法是显式重置每个连接的隔离级别.但这很乏味.

因此,最好的替代方法是为不同的隔离级别创建单独的连接池.

猜你在找的MsSQL相关文章