Insert 语句死锁
Deadlock on Insert statement
使用存储过程将我的列表视图中的一系列记录插入到我的 SQL 服务器 table。但是我遇到了如下图所示的死锁
这是我的程序:
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
根据我的快照,我假设死锁发生在 table 'FVOfficer' 上,但我的 currentFvCollectorid 始终为 0,因此没有执行任何更新语句。但是,我将我的@debtorid 传递给过程 [ValidatePrevCollectorByDebtorID],该过程使用不同的 table 而不是 FVOfficer table 上的游标执行一些验证。可能是参数 @debtorid 被第二个过程锁定,而它在插入中是必需的吗?如果是,请问我该如何解决。
当我检查我的 table 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
抱歉,我把错误的过程作为我的 'ValidatePrevFVCollectorByDebtorID' 发布了。经过深思熟虑。我知道锁定发生在程序 ValidatePrevFVCollectorByDebtorID at
DECLARE LOOPHISTORY_CURSOR CURSOR
FOR SELECT ID,DEBTORID,COLLECTORID,ASSIGNON FROM FVOFFICER
WHERE DEBTORID = @ID ORDER BY ID ASC
OPEN LOOPHISTORY_CURSOR
债务人被锁定在上面。由于我在循环中执行批量插入,因此调用了新的插入实例,但是 debtorid 被锁定在前一个 task/cursor 上。首先
1 我在下面的 select 语句中添加了关键字 with(nolock)
SELECT ID,DEBTORID,COLLECTORID,ASSIGNON FROM FVOFFICER with(nolock)
WHERE DEBTORID = @ID ORDER BY ID ASC
- 然后我在 table FVOfficer 的列 debtorid 上添加了一个非聚集索引以提高我的 select 语句的速度。在我 运行 之后,死锁没有发生。
使用存储过程将我的列表视图中的一系列记录插入到我的 SQL 服务器 table。但是我遇到了如下图所示的死锁
这是我的程序:
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
根据我的快照,我假设死锁发生在 table 'FVOfficer' 上,但我的 currentFvCollectorid 始终为 0,因此没有执行任何更新语句。但是,我将我的@debtorid 传递给过程 [ValidatePrevCollectorByDebtorID],该过程使用不同的 table 而不是 FVOfficer table 上的游标执行一些验证。可能是参数 @debtorid 被第二个过程锁定,而它在插入中是必需的吗?如果是,请问我该如何解决。
当我检查我的 table 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
抱歉,我把错误的过程作为我的 'ValidatePrevFVCollectorByDebtorID' 发布了。经过深思熟虑。我知道锁定发生在程序 ValidatePrevFVCollectorByDebtorID at
DECLARE LOOPHISTORY_CURSOR CURSOR
FOR SELECT ID,DEBTORID,COLLECTORID,ASSIGNON FROM FVOFFICER
WHERE DEBTORID = @ID ORDER BY ID ASC
OPEN LOOPHISTORY_CURSOR
债务人被锁定在上面。由于我在循环中执行批量插入,因此调用了新的插入实例,但是 debtorid 被锁定在前一个 task/cursor 上。首先
1 我在下面的 select 语句中添加了关键字 with(nolock)
SELECT ID,DEBTORID,COLLECTORID,ASSIGNON FROM FVOFFICER with(nolock)
WHERE DEBTORID = @ID ORDER BY ID ASC
- 然后我在 table FVOfficer 的列 debtorid 上添加了一个非聚集索引以提高我的 select 语句的速度。在我 运行 之后,死锁没有发生。