gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-30 01:47:41 28 4
gpt4 key购买 nike

有问题的 Sql Server 2008 R2 实例是重负载 OLTP 生产服务器。几天前出现了死锁问题,但仍未解决。我们收到了 Xml 死锁报告,其中列出了死锁中涉及的存储过程和一些其他详细信息。我将首先尝试从这个 xml 中列出事实:

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

我们调查了以下内容:

  • 我们是否正在设置 SP1 的 IsolationLevel在 SP 或中“可序列化”代码? - 没有。

  • 是任何其他 SP,其 IsolationLevel是“Serializable”调用 SP1 吗? - 没有。

  • SP1 使用的表是否被调用任何其他具有隔离功能的 SP级别为“可序列化”? - 是的。有些 SP 具有 Isolation级别设置为“可序列化”和访问与 SP1 相同的表,但我们不知道他们是否当时正在运行死锁与否作为死锁
    报告仅显示 SP1 和 SP2。

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

  • 发生死锁是因为 SP1作为“可序列化”运行。 - 为什么是这个 SP 在 Serializable 中运行时我没设置?是隔离级别升级(就像锁一样)?如果我们弄清楚了并让它运行ReadCommitted,问题会不会解决了吗?

  • 任何其他 SP 正在运行,锁定SP1 使用的表并导致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 正在执行从 5 个不同表(Table1 到 Table5)中获取数据的选择(使用内部查询等)。SP2 对 Table1 执行更新。
有趣的是 SP2 更新的列之一是 Table1 中的外键字段和 Table2 的主键,而 Table1 和 Table2 都是 SP1 的 select 语句的一部分,不确定这是否相关但不想错过任何东西。

注意:indexname="Index1"(在上面的死锁图中)-- Index1 与表 1 中的外键和表 2 的主键在同一列上。

最佳答案

检查这个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.

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

基本上,如果您有一个连接池并在特定隔离级别打开一个连接,比方说可串行化,那么该连接将返回到隔离级别设置为可串行化的池中。下次请求连接时,您无法确定此连接不会返回,因此即使默认隔离级别为 ReadCommitted,您也可能获得这些“可序列化”连接之一。

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

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

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

关于sql-server - SQL Server 2008 R2(.Net 2.0 应用程序)中的死锁问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3725822/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com