-1

我正在寻找正确的方法来防止由于多个进程尝试更新表中的同一记录而导致死锁问题。我已经能够通过首先选择记录WITH (UPDLOCK)然后进行更新来防止死锁。但是,我不确定这是否会一直有效,或者当其他进程插入新记录或更新此表中的其他记录时,它是否会导致其他阻塞问题。

CREATE PROCEDURE usp_ReduceOrderAmount
           @OrderId         INT,
           @ReductionAmount INT
AS
BEGIN

SET NOCOUNT ON

DECLARE @dDateTime AS DATETIME                  
SET @dDateTime = GETUTCDATE()

BEGIN TRANSACTION

--Quick Fix... Attempt to block other callers who are trying to update the same record. 
SELECT * FROM ORDERS WITH (UPDLOCK) WHERE ORDER_ID = @OrderId

UPDATE dbo.ORDERS
SET QTY_OPEN = QTY_OPEN - @ReductionAmount,
UPDATED_WHEN = @dDateTime
WHERE ORDER_ID = @OrderId           

COMMIT

END
4

1 回答 1

0

首先,我不明白您为什么要在事务中进行选择查询。你没有在更新查询中使用它,所以我认为你可以把它放在外面。

然后,也许你可以尝试改变你的隔离级别

SET TRANSACTION ISOLATION LEVEL
    { READ UNCOMMITTED
    | READ COMMITTED
    | REPEATABLE READ
    | SNAPSHOT
    | SERIALIZABLE
    }
[ ; ]

可以试试这个

READ UNCOMMITTED 指定语句可以读取已被其他事务修改但尚未提交的行。

REPEATABLE READ 指定语句不能读取已被其他事务修改但尚未提交的数据,并且在当前事务完成之前没有其他事务可以修改当前事务已读取的数据。

SNAPSHOT 指定事务中任何语句读取的数据将是事务开始时存在的数据的事务一致版本。事务只能识别在事务开始之前提交的数据修改。当前事务开始后其他事务所做的数据修改对于当前事务中执行的语句是不可见的。效果就好像事务中的语句获得了事务开始时已提交数据的快照。

SERIALIZABLE 指定以下内容: 语句不能读取已被其他事务修改但尚未提交的数据。在当前事务完成之前,任何其他事务都不能修改当前事务已读取的数据。在当前事务完成之前,其他事务不能插入键值落在当前事务中的任何语句读取的键范围内的新行。

于 2013-05-09T17:41:52.030 回答