代码之家  ›  专栏  ›  技术社区  ›  Sidharth Panwar

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

  •  7
  • Sidharth Panwar  · 技术社区  · 14 年前

    死锁涉及两个存储过程,例如SP1和SP2。据介绍 SP2正在“ReadCommitted”中运行 .

    我们调查了以下情况:

    • 在SP内或中“可序列化” 代码?-没有。

    • 是隔离级别为

    • SP1使用的表是否由调用 任何其他具有隔离的SP 级别为“可序列化”?-是的。 存在具有隔离的SP 级别设置为“可序列化”并且 访问与SP1相同的表, 但我们不知道他们 当时正在跑步 死锁与否视为死锁
      报告仅显示SP1和SP2。

    思路:

    • 发生死锁是因为SP1 此SP在以下情况下可序列化运行 我还没定?是隔离吗 水平上升(像锁一样)?如果 重新提交,问题会被解决吗 断然的?

    • SP1使用的表并导致 SP1和SP2之间的死锁。- 这个SP不会列在 这样的依赖?如果是 解决SP1如何在中运行 可序列化的。

    • 如果此信息不充分 从SQL获取更多信息 我的目的是什么 我应该收集什么信息?

    • 你还有别的想法吗 在解决这个问题上追求什么?

    更新:
    这就是 跟踪日志信息

    ?<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个不同的表(表1到表5)中获取数据(使用内部查询等)。SP2在表1上执行更新。
    有趣的是SP2更新的一列是Table1中的外键字段和Table2的主键,而Table1和Table2都是SP1的select语句的一部分,不确定这是否相关,但不想遗漏任何内容。

    3 回复  |  直到 14 年前
        1
  •  2
  •   Sidharth Panwar    13 年前

    看看这个 MSDN article

    与SET事务隔离级别语句的连接,它 在连接关闭或其他隔离之前保持有效 上次设置的事务隔离级别的隔离级别 保留对账单。重用池的后续连接 连接使用在连接时有效的隔离级别 连接已池化。

    问题是,连接是以可序列化隔离级别打开的;关联的事务已被释放,连接也已被释放,但连接未被破坏并转到连接池。下一次请求连接时(使用相同的连接字符串),返回的正是这个连接,因为查询没有指定任何隔离级别,所以它是在可序列化的隔离级别中执行的。

    基本上,如果您有一个连接池,并且在特定的隔离级别(比如Serializable)中打开了一个连接,那么该连接将返回到隔离级别设置为Serializable的池。下一次请求连接时,您无法确定是否不会返回此连接,因此即使默认隔离级别为ReadCommitted,您也可能会得到其中一个“可序列化”连接。

    另一个警告是,每次将隔离级别设置为Serializable(或其他类似的设置)时,您可能会选择不同的连接,并且通过将它们的隔离级别设置为Serializable(或您设置的任何设置),您可能会慢慢地污染连接池中越来越多的连接。

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

    因此,最好的选择是为不同的隔离级别创建单独的连接池

        2
  •  1
  •   saga    14 年前

    在sp1中选定的表之后添加with(nolock),以确保不能向这些特定表添加读锁。

        3
  •  0
  •   Community CDub    8 年前

    SELECT UPDATE 陈述,听起来这可能与你的情况有关。有关详细信息,请参见以下链接:

    推荐文章