在执行读取/更新的MS SQL存储过程中获取死锁(放置代码以处理死锁)

时间:2014-03-01 16:12:09

标签: sql sql-server stored-procedures deadlock

我不得不承认我正在学习如何正确处理死锁,但根据我读过的建议,我认为这是处理它的正确方法。基本上我有很多进程试图在数据库中“保留”一行以进行更新。所以我首先阅读一个可用的行,然后写入它。这不是正确的方法吗?如果是这样,我该如何修复此SP?

CREATE PROCEDURE [dbo].[reserveAccount] 
    -- Add the parameters for the stored procedure here
    @machineId varchar(MAX)
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

BEGIN TRANSACTION;
    declare @id BIGINT;

    set @id = (select min(id) from Account_Data where passfail is null and reservedby is null);

    update Account_data set reservedby = @machineId where ID = @id;

    COMMIT TRANSACTION;
END

2 个答案:

答案 0 :(得分:2)

您可以将其写为单个语句。这可能会解决更新问题:

update Account_data
    set reservedby = @machineId
    where ID = (select min(id) from Account_Data where passfail is null and reservedby is null);

答案 1 :(得分:1)

嗯,你的问题是2你有2个陈述 - 选择和更新。如果那些运行并发,则select将.....进行读锁定,更新将要求写锁定。同时2个机器死锁。

简单的解决方案是使初始选择需求成为uddate锁(WITH(ROWLOCK,UPDLOCK)作为提示)。这可能会或可能不会奏效(取决于还有什么),但这是一个良好的开端。

第二步 - 如果失败 - 是使用应用程序级别锁(sp_getapplock)来确保关键系统始终只有一个所有者,而htus只是按顺序执行事务。