質問
私が抱えている問題は次のとおりです。
次のフィールドを含むテーブル (単なる例) があります。
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 Server 2008 で開発しています。
集団の心は何を考えているのでしょうか?
解決
たぶん私は 以上これについてはよく考えていないのですが、ロジック ブロック全体をラップするだけではだめでしょうか。
- 読み取り値
- 値を書き込む
のデータベーストランザクション内で、 適切なレベル?
SET TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED
| READ COMMITTED
| REPEATABLE READ
| SNAPSHOT
| SERIALIZABLE
}
[ ; ]
所属していません StackOverflow