【问题标题】:Deadlock on Insert statement插入语句死锁
【发布时间】:2015-01-16 08:00:28
【问题描述】:

使用存储过程将一系列记录从我的列表视图插入到我的 SQL Server 表中。但是我遇到了如下图所示的死锁

这是我的程序:

declare @debtorCollectorHistoryId bigint

set @debtorCollectorHistoryId = (Select top 1 id 
                                 from FVOfficer with(nolock) 
                                 where debtorid = @debtorid 
                                 order by id desc)

if @currentFvCollectorid  is null
   set @currentFvCollectorid = (SELECT FvCollectorID 
                                from Debtor with(nolock) 
                                where id = @debtorid)

if @assignon is null
   set @assignon = GETDATE()

      print @debtorCollectorHistoryId
       print @currentFvCollectorid
      print @newFvCollectorid



    if @currentFvCollectorid <> @newFvCollectorid
    BEGIN
        if @currentFvCollectorid <> 0
        Begin   
            update FVOfficer 
            set terminateon = GetDate()
            where id = @debtorCollectorHistoryId
        End

        Begin
        --create new Collector History for new collector
        --NOTE: CurrentCollectorID is a previous collectorID for new Collector History

        insert into FVOfficer (debtorid, prevCollectorID, collectorid, assignon, terminateon, loginID)
        values (@debtorid,@currentFvCollectorid, @newFvCollectorid, GetDate(), null, @loginID)
        print' create new Collector History for new FV collector'

        exec dbo.[ValidatePrevFVCollectorByDebtorID] @debtorid
    end
    begin
        print @debtorid
        update Debtor set FVCollectorid = @newFvCollectorid where id = @debtorid 
    end

从我的快照中,我假设死锁发生在表 'FVOfficer' 上,但我的 currentFvCollectorid 始终为 0,因此不执行更新语句。但是,我将我的@debtorid 传递给过程 [ValidatePrevCollectorByDebtorID],该过程使用游标在不同的表而不是 FVOfficer 表上执行一些验证。可能是参数 @debtoid 被第二个过程锁定,而它在 insert 中是必需的?如果是这样,请问我该如何解决。

当我检查我的表 FVOfficer 时,我注意到它没有主键或任何索引,我索引 id 列,它是一个 identity(1,1) 列。我在 id 上创建了一个聚集索引,但这并不能解决我的问题。请问我该怎么做?

更新 下面是我的 [ValidatePrevFVCollectorByDebtorID] 请问这和这个问题有什么关系吗?

DECLARE @ID AS BIGINT

--LOOP ALL THE DEBTOR COLLECTOR HISTORY ID
----------------------------------------------------------------------------    
DECLARE LOOPDEBTOR_CURSOR CURSOR
    FOR  SELECT ID FROM DEBTOR WITH(NOLOCK) WHERE  ID = @REFDEBTORID
    --WHERE COLLECTORID > 0 

OPEN LOOPDEBTOR_CURSOR

FETCH NEXT FROM LOOPDEBTOR_CURSOR INTO @ID


WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE @COLLECTORYHISTORYID AS BIGINT
    DECLARE @ASSIGNON AS DATETIME
    DECLARE @DEBTORID AS BIGINT
    DECLARE @COLLECTORID AS BIGINT



    DECLARE @PREVCOLLECTORID AS BIGINT 

    --GET THE 1ST HISTORY ID BASE ON DEBTORID
    ---------------------------------------------------------------------------         
    DECLARE @FIRSTID AS BIGINT
    SET @FIRSTID = (SELECT TOP 1 ID FROM  FVOFFICER WITH(NOLOCK) 
        WHERE DEBTORID = @ID ORDER BY ID  )

    -- LIST ALL THE DEBTOR COLLECTOR HISTORY BASE ON DEBTORID = @ID
    ---------------------------------------------------------------------------         
    DECLARE LOOPHISTORY_CURSOR CURSOR
        FOR  SELECT ID,DEBTORID,COLLECTORID,ASSIGNON FROM FVOFFICER 
        WHERE DEBTORID = @ID ORDER BY ID ASC
    OPEN LOOPHISTORY_CURSOR

    FETCH NEXT FROM LOOPHISTORY_CURSOR INTO 
        @COLLECTORYHISTORYID,@DEBTORID,@COLLECTORID,@ASSIGNON

    WHILE @@FETCH_STATUS = 0
    BEGIN


        --FIX PREV COLLECTOR ID VALUE
        IF @FIRSTID != @COLLECTORYHISTORYID
            UPDATE  FVOFFICER SET PREVCOLLECTORID = @PREVCOLLECTORID 
            WHERE ID = @COLLECTORYHISTORYID                                                             

        SET @PREVCOLLECTORID = @COLLECTORID

    FETCH NEXT FROM LOOPHISTORY_CURSOR INTO 
        @COLLECTORYHISTORYID,@DEBTORID,@COLLECTORID,@ASSIGNON
    END

    CLOSE LOOPHISTORY_CURSOR
    DEALLOCATE LOOPHISTORY_CURSOR

FETCH NEXT FROM LOOPDEBTOR_CURSOR INTO @ID


END


CLOSE LOOPDEBTOR_CURSOR
DEALLOCATE LOOPDEBTOR_CURSOR

【问题讨论】:

  • FVOfficer 上有触发器吗?
  • 不,先生。 FVOfficer 上没有触发器。
  • 插入后注释掉所有内容,死锁会消失吗?
  • 不,先生,没有尝试过,我在想,因为我的快照打印了打印“为新的 FV 收藏家创建新的收藏家历史”。那么可能是错误来自我的表。然后我意识到下面的过程有点使用游标。难道是它锁定了@debtorid,然后它需要在另一个新行中连续插入?我想我会尝试评论看看。
  • @Marko .i 添加了第二个 proc 。会不会和我的问题有关?请先生指教。

标签: sql-server stored-procedures deadlock


【解决方案1】:

抱歉,我将错误的过程发布为我的“ValidatePrevFVCollectorByDebtorID”。经过慎重考虑。我知道锁定发生在 ValidatePrevFVColectorByDebtorID 的过程中

 DECLARE LOOPHISTORY_CURSOR CURSOR
        FOR  SELECT ID,DEBTORID,COLLECTORID,ASSIGNON FROM FVOFFICER 
        WHERE DEBTORID = @ID ORDER BY ID ASC
    OPEN LOOPHISTORY_CURSOR

债务人被锁定在上面。由于我在循环中执行批量插入,因此调用了新的插入实例,但是债务人被锁定在前一个任务/光标上。首先

1 我在 select 语句中添加了关键字 with(nolock),如下所示

SELECT ID,DEBTORID,COLLECTORID,ASSIGNON FROM FVOFFICER with(nolock)
                WHERE DEBTORID = @ID ORDER BY ID ASC
  1. 然后我在 FVOfficer 表的 debtorid 列上添加了一个非聚集索引,以提高我的选择语句的速度。在我运行之后,没有发生死锁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 2010-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多