私が抱えている問題はこれです:
次のフィールドを持つテーブル(単なる例)があります。
ID int
Value int
次のことを行う IncreaseByFive() というメソッドがあります。
method IncreaseByFive(int ID)
{
int value = GetValueFromDB(ID);
value = value + 5;
SaveValueToDB(value, ID);
}
私が避けたいのは、次の状況です。
- ユーザー A がメソッドを呼び出し、値を取得します (現在は 5)
- ユーザー B がメソッドを呼び出して値を取得します (現在は 5)
- ユーザー A が値を 5 増やします (現在は 10)
- ユーザー B が値を 5 増やします (現在は 10)
- ユーザー A が値を保存 (10)
- ユーザー B は値を保存します (10)
これで、レコードの値が 15 になるはずが 10 になりました。
私が強制したいのは次のとおりです。
- ユーザー A がメソッドを呼び出し、値を取得します (現在は 5)
- ユーザー B はメソッドを呼び出しますが、A が既に呼び出しているため、待機する必要があります。(ディブ!)
- ユーザー A が値を増やします (現在は 10)
- ユーザー B はまだ待機中です
- ユーザー A が値を保存します (レコードの値は 10)
- ユーザー B は値 (10) を読み取ることができるようになりました。
- ユーザー B が値を増やします (15)
- ユーザー B が値を保存する
これで、レコードの値は 15 になりました。これが、探している結果です。
過去に静的クラスを使用してこの問題を解決し、そのクラスのコンストラクター内で作成された静的オブジェクトにロックを設定して、すべての作業を 1 つの静的メソッドに集中させ、他の呼び出しを順番に待機させました。ただし、これはスケーラブルではありません。
また、トランザクションの最高の分離レベル (シリアル化可能) も、上記の不要な例のステップ 2 での読み取りを許可するため、うまくいかないと思います。
別の解決策は、独自のロックテーブルを作成してそこにロックを記録することだと思いますが、それは必要ではないようです。
私はこのプロジェクトを C# (3.5) と SQL サーバー 2008 で開発しています。
ハイブマインドは何を考えていますか?