-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 に答える