6

現在、一連のレコードを挿入するために使用しているプロセスは次のようなものです。

(「一連のレコード」とは、個人のレコードと住所、電話番号、またはその他の結合されたテーブルのようなものを意味することに注意してください)。

  1. 取引を開始します。
  2. 関連する一連のレコードを挿入します。
  3. すべてが成功した場合はコミットし、そうでない場合はロールバックします。
  4. 次の一連のレコードについては、手順 1 に戻ります。

このようなことをもっとすべきでしょうか?

  1. スクリプトの先頭でトランザクションを開始します
  2. レコードのセットごとにセーブ ポイントを開始します。
  3. 関連レコードのセットを挿入します。
  4. エラーが発生した場合はセーブポイントにロールバックし、すべてが成功した場合は続行します。
  5. スクリプトの先頭でトランザクションをコミットします。

ORA-01555 でいくつかの問題が発生し、Ask Tom の記事 (この記事など) をいくつか読んだ後、2 番目のプロセスを試してみることを考えています。もちろん、Tom が指摘するように、新しいトランザクションの開始は、ビジネス ニーズによって定義されるべきものです。2 番目のプロセスは試してみる価値がありますか、それとも悪い考えですか?

4

2 に答える 2

5

トランザクションは、意味のある作業単位である必要があります。ただし、作業単位を構成するものはコンテキストによって異なります。OLTP システムでは、Unit Of Work はアドレス情報などとともに 1 人の人物になります。しかし、多くの人物をロードする何らかの形式のバッチ処理を実装しているかのように聞こえます。

ORA-1555 で問題が発生している場合は、他のトランザクションによって更新されているデータを提供するクエリを長時間実行しているため、ほぼ確実です。ループ内でコミットすると、UNDO セグメントが循環的に使用されるため、読み取りの一貫性を提供するために依存しているセグメントが再利用される可能性が高くなります。したがって、それを行わないことはおそらく良い考えです。

SAVEPOINT を使用することが解決策であるかどうかは別の問題です。それがあなたの状況でどのような利点をもたらすかわかりません。Oracle10g を使用しているため、代わりに一括DML エラー ログの使用を検討する必要があります。

または、駆動クエリを書き直して、より小さなデータのチャンクで動作するようにすることもできます。あなたのプロセスの詳細についてもっと知らなければ、私は具体的なアドバイスをすることはできません. しかし、一般的には、10000 レコードに対して 1 つのカーソルを開くのではなく、1 回のポップで 500 行に対して 20 回開く方がよい場合があります。考慮すべきもう 1 つのことは、一括コレクションと FORALL を使用するなどして、挿入プロセスをより効率的にすることができるかどうかです。

于 2009-10-03T21:07:10.437 に答える
1

いくつかの考え...

  1. 私には、asktom リンクのポイントの 1 つは、1555 を回避するためにロールバック/元に戻すのサイズを適切に設定することだったようです。これが不可能な理由はありますか?彼が指摘しているように、ディスクを購入する方が、ロールバックの制限を回避するためのコードを作成/維持するよりもはるかに安価です (ただし、36Gb ドライブの 250 ドルの値札を読んだ後、再検討する必要がありました - そのスレッドは 2002 年に始まりました)。 ! ムーアの法則のいい例え!)
  2. このリンク (Burleson)は、セーブポイントで考えられる問題の 1 つを示しています。
  3. 2 番目のシナリオでは、トランザクションは実際のステップ 2、3、および 5 にありますか? もしそうなら、それが私がすることです - 各トランザクションをコミットします。シナリオ 1 はトランザクションのコレクションが 1 つにまとめられているように思えますか?
于 2009-10-03T19:39:32.407 に答える