web-dev-qa-db-ja.com

Oracle-特定のテーブルへのコミットされていない変更を表示する方法はありますか?

私は現在、多くのDMLステートメントを実行するバッチプロセスでデバッグしていますが、すぐにはコミットしません。トランザクションがコミットされていないときに別のセッションからの「保留中の」変更を表示できると便利です。これは可能ですか?

例:

Insert into table myTable (col1, col2) values ("col1", "col2");

--Somehow view the pending transaction maybe by system view?....

...other DML statements....

commit;
24
contactmatt

バッチプロセスの詳細と、コミットされていない変更を表示しようとする理由に応じて、いくつかの異なるアプローチがあります。

1) Oracle Workspace Manager は、Spatialアプリケーションを開発しているユーザーが、非常に長時間実行されるトランザクション(つまり、何日または何週間もの人間がどこにいるのかを把握する必要があるトランザクション)に相当するように設計されたツールです1つのトランザクションでパイプラインを実行します)。バッチプロセスでは、新しいワークスペース(論理的には新しいトランザクションを作成するようなもの)を作成し、必要なときにいつでもコミットしながら、そのワークスペースで必要な変更を行うことができます。別のセッションでは、バッチプロセスのワークスペースに入るまで、コミットされた変更は表示されません。バッチプロセスが完了すると、そのワークスペースをライブワークスペースにマージできます。これは、トランザクションをコミットすることと同じです。

2) DBMS_XAパッケージ を使用すると、あるセッションから別のセッションにトランザクションを「引き渡す」ことができ、あるセッションが別のセッションによって開始されたトランザクションに接続できるようになります。これはかなり不明瞭なパッケージですが、最近 PL/SQLチャレンジ (アクセスするには無料のアカウントが必要になる場合があります)で使用する素晴らしい例がありました。

3)実際のデータを確認するのではなく、バッチプロセスのステータスを確認するだけの場合、バッチプロセスは自律トランザクションを使用してログ情報を書き込み、別のセッションからクエリを実行できます。または、 DBMS_APPLICATION_INFOパッケージ を使用して、アプリケーションにV $ SESSIONやV $ SESSION_LONGOPSのさまざまな属性を更新させ、別のセッションからのロードのステータスを監視することができます。

18
Justin Cave

編集:これは質問が明確になる前に書かれました

フラッシュバッククエリを使用して、ownコミットされていないデータなしでテーブルを表示できます。

考慮してください:

SQL> CREATE TABLE my_table
  2  AS SELECT ROWNUM ID FROM dual CONNECT BY LEVEL <= 5;

Table created

SQL> INSERT INTO my_table VALUES (6);

1 row inserted

自分のトランザクションを含むテーブルと、他の人が見ることができるテーブルの違いを確認するには、次のようにします。

SQL> SELECT * FROM my_table
  2  MINUS
  3  SELECT * FROM my_table AS OF TIMESTAMP (systimestamp);

        ID
----------
         6
10
Vincent Malgrat

Oracleとは コミットされていない読み取り分離モードはありません 。つまり、別のトランザクションでコミットされていないデータをクエリすることはできません。

長時間実行されているトランザクションから情報を取得する方法はいくつかあります。これまでのところ言及されていないのは 自律型トランザクション (注意して使用する必要があります)

はい- LogMiner はこれを行うことができます。実際、コミットされたトランザクションのみが必要な場合は、具体的に filter 出力する必要があります。そこには TABLE_NAME in V$LOGMINER_CONTENTS、それはあなたが単一のテーブルを見る方法です。

8
Gaius

直接的な方法はありません。 (別の回答で述べたように)ログを解析するか、別の方法を使用して、長時間実行されているプロセスで何が起こっているかを確認する必要があります。

個人的には、この機能を有効にするために自律型トランザクションを使用することをお勧めします-トランザクション自体ではなく、何が起こっているかを知らせるロギングメカニズムとして。たとえば、別のテーブルにVARCHAR2を書き込むPROCEDURE LONG_ACTION呼び出しPROCEDURE WRITE_LOG_ENTRY(自律型トランザクションとして定義)を持つことができます。自律型トランザクションは現在のトランザクションに干渉しないため(LOGICALの観点から、パフォーマンスへの潜在的な影響に注意)、現在のトランザクションのCOMMITまたはROLLBACKに関係なく、ログエントリを介して何が起こっているかを確認できます。そうは言っても、1つの大規模なDMLステートメントでそれを行うことができます。ループを使用する必要があります。

考慮してください:

TABLE LOG_ENTRIES defined as
    activity_date  date,
    log_entry varchar2(2000)

TABLE BIG_JOB (definition doesn't really matter)

PROCEDURE WRITE_LOG_ENTRY
                        ( str VARCHAR2 )
IS
    PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
    INSERT INTO LOG_ENTRIES VALUES ( SYSDATE, str );
    COMMIT;
END;

PROCEDURE LONG_ACTION IS
    c NUMBER;
BEGIN
    FOR r IN ( SELECT * FROM BIG_JOB )
    LOOP
       c := c + 1;
       UPDATE BIG_JOB z
          SET fld = hairy_calculation
        WHERE z.rowid = r.rowid;
       IF MOD(c,500) = 0 THEN
           WRITE_LOG_ENTRY ( c || ' rows processed.' );
       END IF;
    END LOOP;
    COMMIT;
END;

上記の場合、長いアクションの成功に関係なく、処理された500行ごとにログエントリが取得されます。機能しているデータを正確に複製する必要がある場合は、複製テーブルを作成し、データを複製するプロシージャ(自律型トランザクション)を呼び出すことをお勧めします。次に、事後的にデータを核にします。 (複製の必要はありません。)

さらに、これがデバッグの目的である場合は、テストが行​​われたときに、そのようなログ記録の必要性を取り除くか、大幅に減らすことをお勧めします。そして、いつものように、自分のシステムでテスト、テスト、テストを行い、どのように機能するかを確認します。 (ロギングがパフォーマンスに劇的な影響を与える良い例については、Niallからのコメントを参照してください。)

(最後に、前に言及しなかったため:自律型トランザクションに注意してください。実装する前に完全に理解し、「単に」という理由で使用しないでください。これらは、100万通りの方法で誤って使用される可能性があります(たとえば、ATTEMPTからトリガーでの変異エラーを回避するため)、可能な場合は常に代替案を見つけることが最善です。それができない場合は、注意して続行してください。長時間実行するオペレーション中のロギングは、かなり安全なケースの1つです(無視するパフォーマンスの問題)。ただし、結果を知らずに他の用途に適用するために急いではいけません。)

5
Kerri Shotts

10gでは使用できませんが、 DBMS_XA を使用すると、トランザクションで複数のセッションを横断できます。これを使用して、2番目のセッションはトランザクションで何が起こっているかを確認できます。

3
Gary

ここでの他の情報に加えて、コミットされていないトランザクションに関する情報を送信するいくつかの追加の方法は、電子メールを送信するか、テキストファイルに書き込むことです。

3
Leigh Riffel