2012-03-28 39 views
-1

私はPL-SQLの新機能ですが、他のRDBMSでも多くのDB経験があります。ここに私の現在の問題があります。バッチ処理、トランザクションをコミットする場合

procedure CreateWorkUnit 
is 
update workunit 
set workunitstatus = 2 --workunit loaded 

where 
    SYSDATE between START_DATE and END_DATE 
and workunitstatus = 1 --workunit created; 

--commit here? 

call loader; --loads records based on status, will have a commit of its own 

update workunit wu 
set workunititemcount = (select count(*) from workunititems wui where wui.wuid = wu.wuid) 
where workunitstatus = 2 

私が見ている動作は、コミットステートメントの有無にかかわらず、2回実行する必要があることです。ステータスを反転すると、ローダーは2回目の実行で実行されます。私はそれをすべて1度に実行したいです。

私はoracleの知恵の言葉に感謝します。

ありがとうございます!

+0

あなたの問題は、私たちに示していないコード、LOADER自体にあります。何らかの理由で、仕事の状態の変化を拾っていない。その理由はいくつかありますが、コードを見ずに提案をするのは難しいです。 – APC

+1

"* call loader *"は正確に何をしますか? –

+1

'loader'がなくても、(a)あなたの' procedure CreateWorkUnit'コード断片が不明です:それは無名ブロック内か、 'CREATE'コマンドの前にありますか? (b) 'CreateWorkUnit'がまったく実行されていることをどのように知っていますか? (c) 'END'が欠落しています。 –

答えて

4

バッチ処理でトランザクションをコミットするタイミングはいつですか?良い質問ですが、あなたが投稿するコードの問題には漠然と関連しているようです。とにかく答えてみましょう。

PL/SQLプロシージャが作業ユニットを完了したときにコミットする必要があります。作業単位はビジネストランザクションです。これは通常、プログラムの終わり、EXCEPTIONセクションの前の最後のステートメントになります。

時にはそれでもない。コミットまたはロールバックの決定は、呼び出すスタックの先頭にあります。 PL/SQLがクライアントから呼び出されている場合(ユーザーが画面のボタンをクリックしている可能性があります)、クライアントはコミットを発行する必要があります。

しかし、バッチプロセスが独自のコミット(およびエラーの場合はロールバック)を管理することは理にかなっていません。しかし、主なポイントは、最上位のプロシージャだけがCOMMITを発行することです。プロシージャが他のプロシージャを呼び出す場合、プログラムと呼ばれるプロシージャはコミットまたはロールバックを発行すべきではありません。エラーを処理する必要がある場合(ログなど)、呼び出し元のプログラムに再提出してください。ロールバックするかどうかをデコードします。すべての呼び出されたプロシージャは同じセッションで実行され、同じトランザクションで実行されるため、呼び出されたプログラムのロールバックはバッチ処理のすべての変更を元に戻します。それは正しくありません。コミットにも同じ理由が当てはまります。

間欠的コミットを使用して長時間実行されるプロセスをより小さな単位に分割するためのアドバイスを読むことがあります。 1000個のインサートごとに。これはいくつかの理由で悪いアドバイスであり、すべてがトランザクションに関連するわけではありません。関連するものは次のとおりです。

  1. コミットを発行すると、リソースのロックが解放されます。これがORA-1555 Snapshot too oldのエラーの原因です。
  2. また、文やトランザクション・レベルでのみ適用される読取り一貫性にも影響します。これはORA-1002 Fetch out of sequenceというエラーの原因です。
  3. 再始動性に影響します。プログラムが30%のレコードを処理できなかった場合、バッチを再実行すると残りの70%のみが処理されると確信できますか?
  4. レコードがコミットされると、他のセッションでこれらの変更が表示される可能性があります。他のユーザーが部分的に変更したデータビューを参照するのは意味がありますか?

したがって、「Oracleの知恵」とは、作業単位ごとに1回のコミットでデータベーストランザクションとビジネストランザクションを常に整列させることです。


誰かがサブプロセスにコミットを発行する方法としてautonmous transactionsを挙げます。これは通常、悪い考えです。自律型トランザクションで行われた変更は、他のセッションでは表示されますが、自社のものでは表示されません。それはまれには意味をなさない。それはまた、私が前に議論した再起動性と同じ問題を引き起こす。

自動トランザクションで使用できるのは、記録アクティビティ(エラーログ、トレース、監査レコード)のみです。幅広いトランザクションで何が起こっても、そのデータを保持する必要があります。プラグマを他の方法で使用することは、確かに問題を悪化させるporrデザインの回避策です。

+0

ここにボランティアの情報に感謝します。私の背景はすべてmssqlであり、私の現在のショップはOracleの顧客です。喜んで、私はSQL標準に書き込むことができ、私はまだ効率的ですが、私はカーソルを書くことに慣れなければならない...彼らは一時的なスペースで簡単です:) –

0

pl/sqlプロシージャでコミットする必要はありません。別のプロシージャの中で呼び出すプロシージャは同じセッションを使用するため、コミットする必要はありません。セッションがロールバックされた場合や例外が発生した場合、プロシージャは完全にロールバックする必要があります。

+0

pl */sql内でコミットできます。 –

+0

プロシージャでコミットできるだけでなく、メイントランザクション(呼び出し元)をコミットすることを防ぐ自律型にすることもできます。 –

+0

@BurhanAli - もちろんPL/SQLプログラムでコミットできます。問題は、そうするべきかどうか、もしそうなら、どこに?呼び出されたプログラムの内部のコミットはおそらく間違った場所にあります。適切にコミットするかロールバックするかの決定は、呼び出しスタックの先頭にあります。場合によっては、これは真実である必要はないが、かなり稀である。 – APC

0

私は自分の問題を誤分類しました。私はこれが取引上の問題だと思って、本当に期待通りに設定されていない私の旗の1つだった.

申し訳ありません。 Josh Robinson

関連する問題