2

家には居住者がいて、どの家にも 2 人の居住者が同じ高さを持つことはできないと仮定します。

  1. ランダムな家を選ぶ
  2. 家の現在の居住者のリストを取得する
  3. リストを調べて、どれを保持、置換、削除、または追加するかを決定します
  4. 新しいリストに同じ身長の居住者が含まれていないことを確認してください。
  5. 既存のリストを新しいリストに置き換えます。必要に応じて削除、挿入、または更新します。

簡単に思えますが、50 個のスレッドがすべて同時にこれを実行しようとすると、複雑になります。私はUPDLOCK、ROWLOCKを選択(ステップ2)で使用して、更新する可能性のある占有者への更新をブロックしました。ただし、現在の居住者がなく、新しい居住者が追加されると、時々失敗します。失敗は常に一意の制約違反です。これは決して起こらないはずですが (手順 4 を参照)、実際に発生します。

手順 2 ~ 5 は、ReadCommitted 分離レベルを使用して TransactionScope 内で実行されています。

このようなシナリオの処理方法を定義するベスト プラクティス モデルはどこかにありますか?

4

2 に答える 2

0

これは SQL または TransactionScope 関連の問題ではないことに気付きました。データ項目のコレクションを調整していますが、その間はコレクションへのアクセスをセマフォする必要があります。私の場合、調整を行うコードの周りに lock(List) { を追加する必要がありました。}

例えを続けると、居住者のリストを照合する場合は、作業中に居住者が出入りするのを防ぐためにドアをロックすることをお勧めします。

于 2013-04-05T22:21:47.463 に答える
0

SQL Serverのトランザクション分離レベルを見てください。あなたの問題は、ファントム読み取りが発生している可能性が高いようです (つまり、誰かが既に選択した範囲にデータを挿入しています)。

このような状況では高レベルの同時実行性があるため、関連するすべてのクエリ (つまり、SELECT の後に適切な INSERT/UPDATE/DELETE が続く) を、分離レベルを Serializable に設定して単一のトランザクションで実行することを強くお勧めします。 . そうすれば、SQL Server は、トランザクションが互いに完全に分離されて発生することを保証します。

ただし、この場合の最善の解決策は、高度な同時実行性を考慮すると、SQL Server だけに頼るのではなく、何らかのロック/同期をコードに実装することでしょう。(ただし、Serializable 分離​​レベルを使用することをお勧めします。)

たとえば、同じ占有者 (または家) に対して常に同じオブジェクトを取得し、各スレッドがそのオブジェクトを使用するように、占有者と家ごとにロック オブジェクトを生成するある種のロック マネージャーを使用します。クリティカルセクション(または同様のC#のものMonitor.Enter)に入るために-デッドロックを避けるように注意してください。こうすることで、常に 1 つのスレッドだけが特定の家または特定の居住者を調べていることを保証できますが、他のスレッドは実行できます。

于 2013-03-16T02:56:20.077 に答える