当我在sql server 2008中调用我的存储过程时,我遇到了死锁问题。一个xml字符串由biztalk传递给存储过程,并且可以快速连续多次调用。我遇到的问题是,如果程序被快速连续调用5次,则前4次调用将被回滚,最后一次调用由于死锁而被提交到数据库。下面是该过程的代码 - 它使用OPENXML解析xml字符串并插入表A.然后我从表A中获取新的唯一标识符并将多个子记录插入表B.任何有关如何解决此问题的指导都将非常感谢。
错误消息: System.Data.SqlClient.SqlException(0x80131904):事务(进程ID XX)在锁资源上与另一个进程死锁,并被选为死锁牺牲品。重新运行该交易。
表格详情
表A
- Id int identity(1,1)主键,
- ColumnA varchar(15)非null,
- ColumnB varchar(20)not null,
- AddedDateTime datetime default(getdate())
表B
- Id int identity(1,1)主键,
- TableAId int not null,(FK)
- ColumnC varchar(30)not null
XML
<Transactions>
<Transaction>
<ColumnA>Column A Value</ColumnA>
<ColumnB>Column B Value</ColumnB>
<ChildItems>
<ChildItem>
<ColumnC>Column C Value</ColumnC>
</ChildItem>
<ChildItem>
<ColumnC>Another Column C Value</ColumnC>
</ChildItem>
<ChildItem>
<ColumnC>Yet Another Column C Value</ColumnC>
</ChildItem>
</ChildItems>
存储过程
CREATE PROCEDURE [dbo].[proc_ProcessXml]
(
@ResponseXml varchar(max)
)
WITH EXECUTE AS CALLER
AS
BEGIN TRANSACTION
DECLARE @xmlHandle int
declare @tableAId int
EXEC sp_xml_preparedocument @xmlHandle OUTPUT, @ResponseXml,
INSERT INTO TableA
(
ColumnA,
ColumnB
)
SELECT columnA, columnB
FROM OPENXML(@xmlHandle, '/Transactions/Transaction', 1)
WITH(
columnA varchar(15) 'ColumnA',
columnB varchar(20) 'ColumnB'
)
select @tableAId = SCOPE_IDENTITY()
INSERT INTO TableB
(
TableAId,
ColumnC
)
SELECT @tableAId, columnC
FROM OPENXML(@xmlHandle, '/Transactions/Transaction/ChildItems/ChildItem', 1)
WITH(
columnC varchar(30) 'ColumnC',
)
EXEC sp_xml_removedocument @xmlHandle
IF @@ERROR <> 0
BEGIN
ROLLBACK
END
ELSE
BEGIN
COMMIT
END
答案 0 :(得分:1)
这种行为可能有很多不同的原因,所以你需要获得更多的事实。您需要知道隔离级别和他们正在争取的锁定。这就是我要做的事情:
select
object_name(P.object_id) as TableName, L.*
into
#preTestLocks
from
sys.dm_tran_locks L
join sys.partitions P on L.resource_associated_entity_id = p.hobt_id
where
object_name(P.object_id) in ('TableA','TableB')
select
object_name(P.object_id) as TableName, L.*
into
#lock1 --<<CHANGE AFTER EACH RUN (#lock2, #lock3 etc.)
from
sys.dm_tran_locks L
join sys.partitions P on L.resource_associated_entity_id = p.hobt_id
where
resource_session_id in (1,2,3,4) --<<YOUR SPID'S
分析结果并查看导致死锁情况的资源。您可能会遇到锁升级问题,这会将行级锁升级到页面或扩展甚至是表级锁。 Read here for a description of Lock Modes
最后一个观察结果:
您可能通过在proc中启动事务并且未指定SET XACT_ABORT ON(See here for details)来玩火。我怀疑这会导致你当前的行为,除非你的客户有超短的超时,但我强烈建议你添加它。