删除SQL然后批量插入死锁

时间:2010-03-22 21:45:28

标签: 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
, [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 Page锁定
  • 在表格上请求X页面锁定

连接2:

  • 在桌面上保持IX Page锁定
  • 请求桌面上的RangeX-X锁定

我需要做些什么才能确保不会发生这些死锁。

我一直在研究RangeX-X锁,我不确定我是否完全理解这些锁的发生情况。我有没有选择锁定整个表格的选项?

2 个答案:

答案 0 :(得分:2)

继Sam Samffron的回答之后:

  • 如果@ ID7 @ SubID是distinc
  • ,请考虑使用READPAST提示跳过任何保持的锁定
  • 考虑SERIALIZABLE并删除XLOCK,HOLDLOCK
  • 为批量插入使用单独的临时表,然后从该
  • 进行复制

答案 1 :(得分:1)

如果没有索引/表大小等列表,很难给出准确的答案,但请记住,SQL无法在同一实例中获取多个锁。它会在一次抓取一个锁,如果另一个连接已经拥有锁并且它对第一个事务需要的东西保持锁定,那么kaboom就会出现死锁。

在这个特定的例子中,您可以做一些事情:

  1. 确保(Id,SubId)上有索引,这样SQL就能够为要删除的数据获取单个范围锁。
  2. 如果死锁变得罕见,请重试死锁。
  3. 您可以使用sledghammer进行此操作并使用不会死锁的TABLOCKX
  4. 使用跟踪标记1204 http://support.microsoft.com/kb/832524获取准确的死锁分析(关于实际死锁的信息越多,就越容易解决)
相关问题