質問

私が抱えている問題は次のとおりです。

次のフィールドを含むテーブル (単なる例) があります。

ID int
Value int

次のことを行う IncreaseByFive() というメソッドがあります。

method IncreaseByFive(int ID)
{    
    int value = GetValueFromDB(ID);
    value = value + 5;
    SaveValueToDB(value, ID);    
}

避けたいのは、次のような状況です。

  1. ユーザー A がメソッドを呼び出し、値 (現在 5) を取得します。
  2. ユーザー B がメソッドを呼び出し、値 (現在 5) を取得します。
  3. ユーザー A は値を 5 増やします (現在は 10)
  4. ユーザー B は値を 5 増やします (現在は 10)
  5. ユーザー A が値 (10) を保存
  6. ユーザー B が値 (10) を保存

レコードの値は 15 になるはずですが、10 になります。

私が強制したいのは次のとおりです。

  1. ユーザー A がメソッドを呼び出し、値 (現在 5) を取得します。
  2. ユーザー B はメソッドを呼び出しますが、A がすでにメソッドを呼び出しているため、待つ必要があります。(ディブス!)
  3. ユーザー A は値を増やします (現在は 10)
  4. ユーザー B はまだ待機中です
  5. ユーザー A が値を保存します (レコードの値は 10)
  6. ユーザー B は値 (10) を読み取ることができるようになりました。
  7. ユーザー B は値を増やします (15)
  8. ユーザー B が値を保存します

これで、レコードの値は 15 になり、これが私が探している結果です。

私は以前、静的クラスを使用し、そのクラスのコンストラクター内で作成された静的オブジェクトにロックを設定して、すべての作業を 1 つの静的メソッドに集中させることで、他の呼び出しをインラインで待機させることにより、この問題を解決しました。ただし、これは拡張性がないのではないかと思います。

また、トランザクションの最も高い分離レベル (シリアル化可能) も、上記の望ましくない例のステップ 2 での読み取りを許可してしまうため、役に立たないと思います。

別の解決策は、独自のロック テーブルを作成し、そこにロックを記録することだと思いますが、それは必要ないようです。

このプロジェクトは C# (3.5) と SQL Server 2008 で開発しています。

集団の心は何を考えているのでしょうか?

役に立ちましたか?

解決

たぶん私は 以上これについてはよく考えていないのですが、ロジック ブロック全体をラップするだけではだめでしょうか。

  • 読み取り値
  • 値を書き込む

のデータベーストランザクション内で、 適切なレベル?

SET TRANSACTION ISOLATION LEVEL
    { READ UNCOMMITTED
    | READ COMMITTED
    | REPEATABLE READ
    | SNAPSHOT
    | SERIALIZABLE
    }
[ ; ]
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top