質問

selectを実行してから、 ResultSet の行の一部をアトミックに更新する必要があります。

使用しているコードは次のようになります(簡略化):

stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
rs = stmt.executeQuery("SELECT ...");

while (rs.next()) {
    if (conditions_to_update) {
        rs.updateString(...);
        rs.updateRow();
    }
}
  • 更新がアトミックに実行されることを保証できますか?そうでない場合、どうすればそれを保証できますか?
  • updateRow()で更新しているデータベース行を他のプロセスが変更した場合はどうなりますか? ResultSet の行をロックする方法はありますか?
役に立ちましたか?

解決

おそらくここにはたくさんのテクノロジーとコンセプトがあり、マルチスレッド/マルチリクエストアプリケーションを検討し始めると、物事はかなり厄介になり始めます。

Iassevkが述べたように、トランザクション更新のアトミックな性質を保証する-非常に低レベルの例は、次の行に沿って何かをすることです:

...
con.setAutoCommit(false);
try {
  while (rs.next()) {
    if (conditions_to_update) {
      rs.updateString(...);
      rs.updateRow();
    }
  }
  con.setAutoCommit(true);
} catch (Exception ex) {
  //log the exception and rollback
  con.rollback();
} finally {
  con.close();
}

その後、すべての更新が同じトランザクションにバッチ処理されます。更新のいずれかが例外を生成した場合(無効な値や結果の途中で接続が失敗した場合など)、ロット全体がロールバックされます。 (最後に私がそれを支持しているので追加しました; p)

ただし、これは、同じテーブルを更新しようとする2つの競合する方法(競合状態)である2番目の問題に対処しません。私の考えでは、ここには2つの主なアプローチがあります。それぞれにメリットとデメリットがあります。

最も簡単なアプローチは、テーブルをロックすることです-これは最小限のコード変更を必要としますが、かなり大きな欠点があります。ほとんどのアプリケーションと同様に、書き込みの方が読みやすいという仮定に基づいて作業します。テーブルをロックすると、他のすべてのユーザーがデータを表示できなくなります。キックして例外をスローします。

より複雑なアプローチは、これらの更新を実行するメソッドがスレッドセーフな方法で実装されるようにすることです。そのために:

  • このテーブルのすべての更新は単一のクラスを通過します
  • そのクラスはシングルトンパターンを実装するか、更新メソッドを静的メソッドとして公開します
  • 更新メソッドは、同期キーワードを利用します競合状態を防ぐため

他のヒント

トランザクションを使用します。

  

updateRow()で更新しているデータベース行を他のプロセスが変更した場合はどうなりますか? ResultSetの行をロックする方法はありますか?

Oracleでは、次のSQLを発行することにより、特定の行を更新用にマークできます。

select cola, colB from tabA for update;

この行を更新しようとする次のトランザクション/スレッド/アプリは例外を取得します。詳細については、これを参照してください- http://asktom.oracle.com/pls/asktom/f?p=100:11:0:::::P11_QUESTION_ID:4530093713805

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top