【问题标题】:How to overcome deadlocks如何克服死锁
【发布时间】:2012-09-05 19:41:57
【问题描述】:

我在尝试运行包含删除语句的存储过程时收到死锁错误。发生的事情是我有一个 FK 约束表行,该行与我要删除的与之相关的表行同时更新。 约束表中正在更新的数据不再重要,任何人都将不再出于任何原因访问正在更新的数据的检索,碰巧这种更新和删除都可以同时发生。所以,我需要以删除为主要操作。

我需要做什么来阻止这样的死锁?

DELETE FROM Storefront.Sidelite WHERE ID = @SideliteID;

下面是 Sidelite 表和 Size 约束表的屏幕截图。

好的,这里没有读取。发生的唯一类型的事情是对 Size 表的许多更新,而 Sidelite 表试图删除它的大小正在更新的记录,这会导致死锁。

在sidelite表中发生删除时,我需要停止对Size表的所有操作,然后,我将在触发器中删除相关的大小记录。

【问题讨论】:

  • 你有什么索引? UPDATE 声明是什么?什么 RDBMS 和版本? FK 约束的定义是什么?它会级联吗?

标签: sql deadlock


【解决方案1】:

在获取初始值的 select 语句中,您可以使用 with(readuncommitted) 或 with(nolock) 语句。然而,这会给你带来脏读。请使用以下链接了解更多信息:Why use a READ UNCOMMITTED isolation level?

【讨论】:

    【解决方案2】:

    1.) SET ALLOW_SNAPSHOT_ISOLATION ON

    2.) SET TRANSACTION ISOLATION LEVEL SNAPSHOT

    ALTER proc [Storefront].[proc_DeleteSidelite]
    @SideliteID INT
    AS
    BEGIN
    SET TRANSACTION ISOLATION LEVEL SNAPSHOT
    
      DECLARE @SizeID INT; 
            BEGIN TRAN
              SELECT @SizeID= sl.SizeID FROM Storefront.Sidelite sl 
                                        with(nolock) WHERE sl.ID = @SideliteID
              DELETE FROM Storefront.Sidelite WHERE ID = @SideliteID;
              DELETE FROM Storefront.Size  WHERE ID=@SizeID;
            COMMIT TRAN
    END;
    

    【讨论】:

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