7

@Transactional アノテーションだけでコードとトランザクションの実行を管理する方法について質問があります。正しくセットアップされた Spring アプリケーションと次のコードがあるとします。

@Transactional
public void withdraw(int amount) {
    if(isEnoughFunds(amount)) {
        decreaseFunds(amount);
    }
}

次のシナリオが発生する可能性はありますか。

  • 資金 == 100; 金額 == 100
  • スレッド A が撤回に入る / トランザクション A が開始する
  • スレッド A は、true と評価される isEnoughFunds を実行します
  • スレッド B が撤回に入る / トランザクション B が開始する
  • スレッド B は、true と評価される isEnoughFunds を実行します。
  • スレッド A は reduceFunds を実行します / スレッド A は db レコードをロックします
  • スレッド B は、スレッド A がトランザクションをコミットして書き込みロックを解放するのを待ちます。
  • スレッド A が撤退を終了する / トランザクション A がコミットする
  • スレッド B は reduceFunds を実行します / スレッド B は db レコードをロックします
  • スレッド B は撤退を終了する / トランザクション B はコミットする
  • 資金 == -100

これが可能である場合、どのようにそれを防ぎますか?

4

1 に答える 1

3

はい、分離レベルによっては可能です。これを防ぐには、ifEnoughFunds() を呼び出す前にデータベースから読み取りロックを明示的に取得します。ロックはトランザクションの終了時に解放されます。このシナリオでは、スレッド B は常にスレッド A のトランザクションがコミットされるのを待ってからチェックします。

于 2012-09-26T16:58:52.127 に答える