gpt4 book ai didi

sql - 重试 INSERT 导致的死锁

转载 作者:行者123 更新时间:2023-12-04 06:04:15 27 4
gpt4 key购买 nike

下面的 sproc 尝试向表中插入一行并生成一个随机 ID,用于在相应表上进行 PK。与随机生成的 ID 的冲突在 catch 块中处理,在那里再次重试/调用该过程。现在,这需要很长时间并导致死锁,因为锁会保留很长时间。有没有办法在重试之前立即释放死锁,以便其他线程可以成功锁定PK索引时有一个短窗口?


CREATE PROCEDURE addPerson
(
@FirstName nvarchar(100),
@LastName nvarchar(100)
)
AS
BEGIN
SET NOCOUNT ON;

DECLARE @PersonId int

-- generate random PersonId
-- this sproc can generate ids that already exist in the table
EXEC generateRandomPersonId @PersonId=@PersonId OUTPUT

BEGIN TRY
INSERT INTO [dbo].[Persons]
(
PersonId,FirstName,LastName
)
VALUES
(
@PersonId,@FirstName,@LastName
)

BEGIN CATCH
--
-- HOW TO RELEASE LOCKS HERE that are still held
-- for the previous INSERT statement?
--

DECLARE @ErrorNumber int, @ErrorMessage nvarchar(2048)
SELECT @ErrorNumber=ERROR_NUMBER(),
@ErrorMessage=ERROR_MESSAGE()

-- if a race condition happened and
-- PersonId happened to be picked already, retry all over again
IF (@ErrorNumber = 2601 OR @ErrorNumber = 2627 AND CHARINDEX(N'PK_Persons_PersonId', @ErrorMessage) > 0)
BEGIN
--
-- RETRYING HERE participates in a high possibility and
-- occurrence of deadlocks
--
EXEC addPerson @FirstName,@LastName
END
ELSE
-- some other error, rethrow it
EXEC rethrowError
END
END CATCH
END
GO

最佳答案

进程不会因自己的锁而阻塞。由于对存储过程的调用在同一个进程中运行,因此第二个 insert 是不可能的。等待来自第一个 insert 的锁.

你能发布一个死锁图吗?这显示了有关阻塞进程的大量信息。

作为快速修复,您可以在循环中搜索免费 ID,这将避免大多数(但不是全部)可能的冲突:

while 1=1
begin
EXEC generateRandomPersonId @PersonId=@PersonId OUTPUT
if not exists (select * from Persons where PersonId = @PersonID)
break
end

关于sql - 重试 INSERT 导致的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8567347/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com