【问题标题】:Transaction (Process ID) was deadlocked on lock - deadlock errors on table update事务(进程 ID)因锁定而死锁 - 表更新时出现死锁错误
【发布时间】:2021-09-16 09:08:17
【问题描述】:

我有一个存储过程,它可以像这样更新一些表:

CREATE PROCEDURE SP_UpdateSomeTables
  @bundleId bigint, 
  @wfStage tinyint
AS
  SET XACT_ABORT ON
  
  SET NOCOUNT ON        
  
  BEGIN TRANSACTION

    UPDATE 
      table1
    SET 
      [LastUpdated] = GETDATE(),
      [WorkflowStage] = @wfStage
    WHERE 
      [Id] = @bundleId
    
    UPDATE 
        table2
    SET
        [LastModified] = GETDATE(),
        [WorkflowStage] = @wfStage
    WHERE
        [ResultBundleId] = @bundleId AND
        [IsCancelled] = 0      
    
  COMMIT TRANSACTION

GO

我收到以下错误:

事务(进程 ID 69)因锁定而死锁 |与另一个进程通信缓冲区资源,并已被选为死锁牺牲品。重新运行事务。

还有其他 SELECT 查询在同一组表上并行运行。

如何避免死锁?

【问题讨论】:

  • 仅供参考,sp_ 前缀由 Microsoft 保留,用于 S 特殊 P 程序。它应该用于用户存储过程名称。使用前缀会带来性能成本,并可能导致您的过程在更新或升级后根本无法工作。这也在documentation 中被警告。
  • 死锁的原因和解决方法有很多 - 表扫描或锁升级、跨多个事务的操作顺序等 - 需要更多信息 - 表模式、所涉及表的索引、执行计划、死锁图、使用的隔离级别等
  • @Larnu 感谢您的提醒。我没有意识到这一点。不幸的是,这是一个棕地项目,无法重命名 db 对象...
  • 解决死锁的第一步是检查死锁图以确定发生死锁的资源。在寻求帮助时,您需要向我们提供死锁图。
  • 通常可以通过查询和索引调优来减少死锁。检查死锁中涉及的查询的执行计划,以确保只触及需要的行。

标签: sql-server tsql deadlock database-deadlocks


【解决方案1】:

我认为您有一个查询 table1 和 table2 在后台运行的视图。在第一次更新后添加提交事务,然后在第一次提交后调用另一个开始事务。

CREATE PROCEDURE SP_UpdateSomeTables
  @bundleId bigint, 
  @wfStage tinyint
AS
  SET XACT_ABORT ON

  SET NOCOUNT ON        

  BEGIN TRANSACTION

    UPDATE 
      table1
    SET 
      [LastUpdated] = GETDATE(),
      [WorkflowStage] = @wfStage
    WHERE 
      [Id] = @bundleId
  COMMIT TRANSACTION --add this

  BEGIN TRANSACTION -- add this
    UPDATE 
        table2
    SET
        [LastModified] = GETDATE(),
        [WorkflowStage] = @wfStage
    WHERE
        [ResultBundleId] = @bundleId AND
        [IsCancelled] = 0      

  COMMIT TRANSACTION

【讨论】:

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