0

、UPDLOCKを持つテーブルにストアドプロシージャを実行するときにデッドロックの回避。私は、ユーザーがWebページを訪問するたびに実行されるストアドプロシージャを維持していますHOLDLOCK

-- Existing tables 
CREATE TABLE SourceAccount 
(
    Id bigint NOT NULL, 
    Value varchar(50) NOT NULL, 
    UpdateTime datetime2 NULL 
) 

CREATE TABLE TargetAccount 
(
    Id bigint NOT NULL, 
    Value varchar(50) NOT NULL, 
    UpdateTime datetime2 NULL 
) 

CREATE TABLE UpdatedCustomers 
(
    CustomerID bigint NOT NULL, 
    SyncTime datetime2 NOT NULL 
) 

ストアドプロシージャ:

CREATE PROCEDURE TriggerAccountSync (
    @CustId bigint,  
    @LastUpdate DATETIME2) 
AS 
BEGIN 
    --if customer is outdated 
    IF EXISTS(SELECT 1 FROM UpdatedCustomers 
       WHERE CustomerID = @CustId AND SyncTime < @LastUpdate) 
    BEGIN 
     BEGIN TRY 
      INSERT INTO TargetAccount(Id, Value) 
       SELECT Id, Value 
       FROM SourceAccount 
       LEFT OUTER JOIN TargetAccount WITH (UPDLOCK, HOLDLOCK) ON TargetAccount.Id = SourceAccount.Id 
       WHERE SourceAccount.UpdateTime IS NULL 

      DELETE FROM TargetAccount 
      FROM SourceAccount 
      INNER JOIN TargetAccount WITH (UPDLOCK) ON TargetAccount.Id = SourceAccount.Id 
      WHERE TargetAccount.UpdateTime < @TimeStamp 

      UPDATE UpdatedCustomers 
      SET SyncTime = @LastUpdate 
      WHERE CustomerID = @CustId    
     END TRY 
     BEGIN CATCH 
     --there are multiple simultaneous calls, it can fail with deadlock 
     --don't raise error 
     END CATCH 
    END 
END 

私はTRY CATCH THROW END CATCHを使用して例外をスローし、まだTargetAccountテーブル上のデッドロックを回避することはできますか?私はそれが同期に失敗したときを知る必要があります。

ストアドプロシージャが完了しなかった場合は、テーブルのロックを解除する方法はありますか?

+0

なぜ 'HOLDLOCK'?私の理解から、それはそのテーブルのセマンティクスを事実上 'SERIALIZABLE'分離レベルに変更します。並行性が低下するため、これらの分離セマンティクスが必要です。 –

+0

@BenThul:TargetAccountテーブルは、同時に(複数のWebページから)、または様々な顧客が同時に同じ顧客によって更新することができます。したがって、そのテーブルへのダーティ・リード/ライトを確実にしたいと考えています。 –

+0

SQLでは、デフォルトではダーティ・リードを取得しません。 「汚れた書き込み」については、同じ行を同時に更新する複数の人がいると仮定します。そのためには、クエリヒントを使用するのではなく、明示的なトランザクションですべてを処理していたと思います。しかし、私はあなたではありません。 –

答えて

2

表ロックは、トランザクションスコープです。ストアドプロシージャに関連付けられている暗黙のトランザクションのみがある場合、ストアドプロシージャが終了するとすぐに、エラーに関係なくロックもロックされます。混乱時にトランザクションが存在しないように

このようなロックを扱う、あなたがロックの寿命をより詳細に制御を持っているように、明示的なトランザクションを使用し、(コードでは、それがより明確にするために一般的に有用です入れ子になっています)。

+0

あなたは例外があるときに我々はロックの寿命を制御することができます例を与えることができますか? –

+0

@DioPhungそれは同じ文章です - 明示的なトランザクションを使用してください。 – Luaan

関連する問題