【问题标题】:Transaction (Process ID) was deadlocked事务(进程 ID)已死锁
【发布时间】:2015-07-21 10:52:10
【问题描述】:

我有一个悲观并发的应用程序锁,并在 Asp.Net Mvc 中生成代码。

using (var scope = new TransactionScope())
{
      using (var context = new Context())
      {
           var submitedEntity = context.Entities.Add(entity);
           context.SaveChanges();
           context.Entry(submitedEntity).Reload();
           code = submitedEntity.Code;

           scope.Complete();
      }
}

并在 SQL Server 触发器中生成代码

Create  Trigger     [dbo].[OnInsertEntity]
On  [dbo].[TableName]
After   Insert
As
Begin
Begin   Transaction
    Declare @ID     BigInt,
        @LastCode   Int,
        @Length     Int,
        @Code       nChar(5)

Select  @ID     = ID
    From    Inserted

Select  @LastCode   = Max(Convert(Int, Code))
    From    [TableName]
    With    (TABLOCKX, HOLDLOCK)

If  @@RowCount      = 0
    Set @LastCode   = 0

Waitfor Delay '00:00:05'

Select  @Length     = Max_Length
    From    Sys.Columns
    Where   Name        = N'Code'   And
        [Object_ID] = Object_ID('[TableName]')

Select  @LastCode   = @LastCode + 1,
    @Code       = Replicate('0', @Length - Len(@LastCode)) + Convert(nChar, @LastCode)


Update  [TableName]
    Set Code    = @Code
    Where   ID  = @ID
Commit  Transaction
End

错误:

catch (DbUpdateException ex)

事务(进程 ID)在锁定资源上与另一个死锁 进程并被选为死锁受害者。重新运行事务。

有什么问题?

谢谢。

【问题讨论】:

  • 哎呀,tablockx + waitfor 触发器延迟。
  • 除了您的逻辑存在严重缺陷之外,当对多行进行插入/更新时,SQL Server 中插入和删除的表可以(并且将)包含多于一行
  • Waitfor Delay '00:00:05' 用于测试悲观并发

标签: sql asp.net sql-server asp.net-mvc entity-framework-6


【解决方案1】:

如果我正确理解您的代码,您似乎只是想为每一行更新一个运行数字,它实际上是一个包含前导零的 nchar 字段。

在整个表上使用具有排他锁的触发器等听起来是个坏主意。我宁愿建议您在表中使用身份字段。如果您确实需要前导零,我只需将计算列添加到使用标识字段进行编号的表中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多