2009-05-29 6 views
1

私はビジネスエンティティを更新するルーチンを持っています。このアップデートには、約6種類のテーブルが含まれています。すべてのコマンドがトランザクション内で実行されています。これらのデッドロックを回避するにはどうすればよいですか?

最近、データベースからルックアップテーブルにアクセスするルーチンにコードを追加する必要がありました。ルックアップ・コードはすでに別のビジネス・オブジェクトに存在していたため、そのビジネス・オブジェクトを使用しました。例:

Using tr As DbTransaction = myConnection.BeginTransaction() 
    ExecuteCommand1(tr) 
    ExecuteCommand2(tr) 
    If myLookupTable.GetLookupTable().FindById(id).HasFlagSet Then 
     ExecuteCommand3(tr) 
    End If 
End Using 

ただし、ルックアップ・テーブル・ビジネス・オブジェクトはハング/デッドロックです。これは、元のルーチンで使用されているトランザクションへの参照がないためです。

調査をした後、ルックアップテーブルロジックをIsolationLevelReadUncommittedに設定して、独自のトランザクションに入れようとしました。これは、私が望む結果を私に与えました。しかし、さらなる研究の後、私はこれを正しく実装したかどうかを第二に推測しています。

アクティブなトランザクションへの参照が自分のルックアップテーブルオブジェクトで使用できないと仮定して、私がベストプラクティスとみなしたことはありますか?私は何かが欠けているように感じる。

+0

ルックアップテーブルでcommand1またはcommand2が何かしますか? –

+0

いいえ、そうではありません。彼らはそれを読むことさえしません。しかし、彼らはルックアップテーブルへのFKを持っているテーブルで動作します。それは直感的に私にロックの問題を示唆するものではありません。

答えて

3

トランザクションの途中で読み込みを行っている場合は、別のトランザクションやダーティリードを使用せずに、トランザクションコンテキストで読み込みを行う必要があります。幸運にも簡単な解決策があります.ADO.Netトランザクションオブジェクトを使用する代わりに.Net TransactionScopeオブジェクトを使用します。 ADO.Netコードはそれに敏感で、他のビジネスコンポーネントの読み取りを含め、このトランザクションでのすべての操作を登録します。ビジネスオブジェクトが別の接続を開かないようにするだけで、既存のトランザクションを分散トランザクションにエスカレートし、そのトランザクションに新しい接続を登録しようとします。

代わりに、各呼び出しでSqlConnection/SqlTransactionのペアを渡すこともできますが、これはコード内のいたるところでひどく醜い形で伝播します。

0

私の場合はロジックを書き換えて、コミットされていない読み取りを行う必要はありません。

0

デッドロックを回避するというゴールデンルールは、すべてのトランザクションで常に同じ順序でテーブルロックを取得することです。だから、他のトランザクションのコードを見て、彼らがテーブルロックを取る順序を見てください。あなたのトランザクションで同じ注文を使用していることを確認してください。

0

あなたのルックアップは、トランザクションtrによって排他的にロックされている行にアクセスしようとしています。読み取りコミットされたトランザクションを使用するか、ルックアップクエリでWITH(NOLOCK)を使用すると、発生している可能性のあるトランザクションによってコミットされていない変更がすべて表示され、ルックアップロジックが実行されます。だから私はそれがどれくらい望ましいか分からない。

あなたは、そのトランザクション中にルックアップを行う必要がある場合、検索クエリが現在のトランザクションに確実に参加するようにすることをお勧めします。これらの操作がすべて同じスレッドで実行される場合は、トランザクションオブジェクトを作成するときにトランザクションオブジェクトをスレッドローカルストレージに格納し、GetLookupTableメソッドでスレッドローカルストレージにトランザクションオブジェクトがあるかどうかを確認し、トランザクションセットであれば、そのトランザクションオブジェクトからの接続を取得できます。それ以外の場合は、新しい接続を作成します。このようにして、ルックアップはそのトランザクションの一部となり、現在のトランザクションによってブロックされることなくロジックを実行し、現在のトランザクションをブロックし、デッドロックにつながるはずです。

関連する問題