Sql server 删除然后大容量插入时的SQL死锁

Sql server 删除然后大容量插入时的SQL死锁,sql-server,tsql,deadlock,Sql Server,Tsql,Deadlock,我有一个SQL Server死锁问题,我无法解决 基本上,我有大量并发连接(来自许多机器),它们执行事务,首先删除一系列条目,然后使用批量插入在相同范围内重新插入条目 本质上,事务看起来是这样的 BEGIN TRANSACTION T1 DELETE FROM [TableName] WITH( XLOCK HOLDLOCK ) WHERE [Id]=@Id AND [SubId]=@SubId INSERT BULK [TableName] ( [Id] Int , [SubId] Int

我有一个SQL Server死锁问题,我无法解决

基本上,我有大量并发连接(来自许多机器),它们执行事务,首先删除一系列条目,然后使用批量插入在相同范围内重新插入条目

本质上,事务看起来是这样的

BEGIN TRANSACTION T1
DELETE FROM [TableName] WITH( XLOCK HOLDLOCK ) WHERE [Id]=@Id AND [SubId]=@SubId

INSERT BULK [TableName] (
[Id] Int
, [SubId] Int
, [Text] VarChar(max) COLLATE SQL_Latin1_General_CP1_CI_AS
) WITH(CHECK_CONSTRAINTS, FIRE_TRIGGERS)

COMMIT TRANSACTION T1
批量插入仅在同一事务中插入与删除的Id和SubId匹配的项。此外,这些Id和SubId条目不应重叠

当我有足够的这种形式的并发事务时,我开始看到这些语句之间有大量的死锁

我添加了锁定提示XLOCK HOLDLOCK来尝试处理这个问题,但它们似乎没有什么帮助

此错误的规范死锁图显示:

连接1:

  • 在PK_TableName上保存RangeX-X
  • 在表上保留IX页锁
  • 正在请求表上的X页锁
连接2:

  • 在表上保留IX页锁
  • 请求表上的RangeX-X锁
为了确保这些死锁不会发生,我需要做什么


我一直在读一些关于RangeX-X锁的书,但我不确定我是否完全理解这些锁到底是怎么回事。除了锁定整个表之外,我还有其他选择吗?

如果没有索引/表大小等列表,很难给出准确的答案,但是请记住,SQL不能在同一个实例中获取多个锁。它将一次一个地抓取锁,如果另一个连接已经持有锁,并且它持有第一个事务所需的某个锁,那么就会出现死锁

在这种情况下,您可以做以下几件事:

  • 确保(Id,SubId)上有一个索引,这样SQL就能够为被删除的数据获取一个范围锁
  • 如果死锁变得罕见,请重试死锁
  • 您可以使用Sledghamer和TABLOCKX来实现这一点,它永远不会死锁
  • 使用跟踪标志1204获得准确的死锁分析(关于实际死锁的信息越多,处理起来就越容易)

  • 以下是Sam Saffron的回答:

    • 如果出现以下情况,请考虑READPAST提示跳过任何保留的锁@ID7@SubID伊斯特公司
    • 考虑可序列化并删除XLOCK,HOLDLOCK
    • 对批量插入使用单独的暂存表,然后从该表复制