4

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か?
4

3 に答える 3

4

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

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つの主要なアプローチがあります。それぞれに長所と短所があります。

最も簡単なアプローチは、テーブルをロックすることです。これには最小限のコード変更が必要ですが、かなり大きな欠点があります。ほとんどのアプリケーションと同様に、書き込みよりも読み取りが多いという前提で作業します。テーブルをロックすると、他のすべてのユーザーがデータを表示できなくなり、コードがハングして、接続がタイムアウトする前にロックが解除されるのを待つ可能性があります。キックインして例外をスローします。

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

  • このテーブルのすべての更新は、単一のクラスを通過します
  • そのクラスはシングルトンパターンを実装するか、更新メソッドを静的メソッドとして公開します
  • 更新メソッドは、競合状態を防ぐためにSynchronizedキーワードを利用します
于 2008-10-17T09:02:48.197 に答える
0

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

于 2008-10-17T14:47:07.550 に答える
0

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

于 2008-10-17T08:27:51.183 に答える