5

このストアド プロシージャを実行すると、デッドロックが発生します。

-- Delete transactions
delete from ADVICESEQUENCETRANSACTION
where ADVICESEQUENCETRANSACTION.id in (
  select TR.id from ADVICESEQUENCETRANSACTION TR
  inner join ACCOUNTDESCRIPTIONITEM IT on TR.ACCOUNTDESCRIPTIONITEMID = IT.id
  inner join ACCOUNTDESCRIPTION ACC on IT.ACCOUNTDESCRIPTIONID = ACC.id
  inner join RECOMMENDATIONDESCRIPTION RD on ACC.RECOMMENDATIONDESCRIPTIONID = RD.id
  inner join RECOMMENDATION REC on REC.id = RD.RECOMMENDATIONID
  inner join ADVICESEQUENCE ADV on ADV.id = REC.ADVICESEQUENCEID
  where adv.Id = @AdviceSequenceId AND (@RecommendationState is NULL OR @RecommendationState=REC.[State])
    );

テーブルのスキーマは次のとおりです。

テーブルのスキーマ

デッドロック グラフは次のとおりです。

ここに画像の説明を入力

ここでデッドロック グラフの詳細を確認できます

そのため、ressource ノードの associatedobjid を取得すると、それがテーブル AdviceSequenceTransaction の主キーとインデックスであることがわかります。

SELECT OBJECT_SCHEMA_NAME([object_id]), * ,
OBJECT_NAME([object_id]) 
FROM sys.partitions 
WHERE partition_id = 72057595553120256 OR partition_id = 72057595553316864;

SELECT name FROM sys.indexes WHERE object_id = 31339176 and (index_id = 1 or index_id = 4)

PK_AdviceSequenceTransaction IX_ADVICESEQUENCEID_ADVICE

テーブル AdviceSequenceTransaction のキー ParentTransactionId とキー プライマリ キーに関係があるため、ParentTransactionId 列にインデックスを作成しました。

そして、デッドロックはもうありません。しかし、問題は、デッドロックがなくなった理由が正確にわからないことです:-/

さらに、それをテストするデータのセットでは、ParentTransactionId にデータがありません。すべてNULLです。

では、ParentTransactionId にデータ(null)がなくても、SQL Server による主キーへのアクセスはありますか???

もう1つのことは、削除ステートメントで結合を削除したいということです:

delete from ADVICESEQUENCETRANSACTION
where ADVICESEQUENCETRANSACTION.id in (
  select TR.id from ADVICESEQUENCETRANSACTION TR
  inner join ACCOUNTDESCRIPTIONITEM IT on TR.ACCOUNTDESCRIPTIONITEMID = IT.id
  inner join ACCOUNTDESCRIPTION ACC on IT.ACCOUNTDESCRIPTIONID = ACC.id
  inner join RECOMMENDATIONDESCRIPTION RD on ACC.RECOMMENDATIONDESCRIPTIONID = RD.id
  inner join RECOMMENDATION REC on REC.id = RD.RECOMMENDATIONID
  inner join ADVICESEQUENCE ADV on ADV.id = REC.ADVICESEQUENCEID
  where adv.Id = @AdviceSequenceId AND (@RecommendationState is NULL OR @RecommendationState=REC.[State])
    );

の中へ :

delete from ADVICESEQUENCETRANSACTION
where ADVICESEQUENCETRANSACTION.id in (
  select TR.id from ADVICESEQUENCETRANSACTION TR
  inner join ACCOUNTDESCRIPTIONITEM IT on TR.ACCOUNTDESCRIPTIONITEMID = IT.id
  inner join ACCOUNTDESCRIPTION ACC on IT.ACCOUNTDESCRIPTIONID = ACC.id
  inner join RECOMMENDATIONDESCRIPTION RD on ACC.RECOMMENDATIONDESCRIPTIONID = RD.id
  inner join RECOMMENDATION REC on REC.id = RD.RECOMMENDATIONID
  where TR.AdviceSequenceId = @AdviceSequenceId AND (@RecommendationState is NULL OR @RecommendationState=REC.[State])
    );

最後の結合を削除しました。しかし、これを行うと、再びデッドロックが発生します。ここでも、理由はわかりません...

あなたの啓発をありがとう:)

4

2 に答える 2

2

WHERE 句で複雑な複合結合を使用すると、問題が発生することがよくあります。SQL Server は、次の論理処理順序を使用して句を処理します (こちらを参照)。

  1. から
  2. オン
  3. 加入
  4. どこ
  5. グループ化
  6. WITH CUBE または WITH ROLLUP
  7. 持っている
  8. 選択する
  9. 明確
  10. オーダーバイ

ビュー、または派生テーブルまたはビューを使用すると、論理的な実行順序を使用するためにクエリの重点がより適切に調整されるため、目的の結果を得るために必要な反復 (TABLE) スキャンの数が大幅に削減されます。各派生テーブル (またはビュー) の FROM 句が最初に実行され、渡される結果セットが ON 原因に制限され、次に JOIN 句などが実行されます。 「最も外側のWHERE」。

したがって、コードは次のようになります。

delete from (SELECT   ADVICESEQUENCETRANSACTION
             FROM     (SELECT tr.id 
                      FROM ADVICESEQUENCETRANSACTION WITH NOLOCK
                      WHERE AdviceSequenceId = @AdviceSequenceId
                      )TR
            INNER JOIN (SELECT [NEXT COLUMN]
                        FROM [NEXT TABLE] WITH NOLOCK
                        WHERE COLUMN = [PARAM]
                        )B
            ON        TR.COL = B.COL            
            )ALIAS
            WHERE [COLUMN] = COL.PARAM
);

など... (コードをカットアンドペーストで使用できないことはわかっていますが、一般的なアイデアを伝えるのに役立つはずです)

このようにして、最初にパラメーターを「内部クエリ」に渡し、制限された結果セットを事前にロードして (特にビューを使用する必要がある場合)、外部に向けて作業します。適切な場所でロック ヒントを使用すると、発生する可能性のある問題のいくつかを防ぐのにも役立ちます。この手法は、実行計画をより効果的にして、ブロックがまだある場合にブロックがどこから来ているかを診断するのにも役立ちます。

于 2013-11-13T12:02:06.240 に答える
0

1 つのアプローチは、ダーティ リードを気にしない場合、テーブル ADVICESEQUENCETRANSACTION TR で WITH (nolock) を使用することです。

于 2013-10-20T23:18:48.797 に答える