Logo   Oracle Knowledge - KROWN: 130941 (Doc ID: 1744301.1)

Last update : 2024-09-19  

    [ 対象リリース ] 
    Oracle8 Database 以後のリリース
    
    [ 対象プラットフォーム ]
    すべてのプラットフォーム

    トラブルシューティングの手順
    [ 詳細 ]
    目的
    ----
    この文書の目的は、マテリアライズド・ビューのリフレッシュの診断手順を説明することです。
    この文書では、次の点について調べる方法を取り上げます。
    
    - 現在リフレッシュが実行中であるかどうか
    - リフレッシュが停止しているのか、ゆっくり実行されているのか
    - 次回のリフレッシュがいつ実行されるか、および前回のリフレッシュがいつ実行されたか
    - 現在リフレッシュのどのフェーズが実行されているか
    - グループ内のどのマテリアライズド・ビューがリフレッシュされているか
    
    この文書は、マテリアライズド・ビューのリフレッシュの進行を診断、および監視するサポート・アナリストやお客様の支援を目的としています。
    マテリアライズド・ビューとスナップショットは、同じ意味を持つ用語です。
    この文書では、全体にわたって、マテリアライズド・ビューを指す用語として MVIEW を使用しています。
    
    リフレッシュの進行の診断
    ========================
    
    目次
    ----
    
    1. リフレッシュ・プロセスの概要
    
    2. 現在リフレッシュが実行中であるかどうかの確認
    
       2.1 特定のMVIEWがリフレッシュ中であるかどうかの確認
       2.2 リフレッシュ・グループがリフレッシュ中であるかどうかの確認
    
    3. 前回および次回のリフレッシュ日の確認
    
    4. リフレッシュ・グループのどのMVIEWがリフレッシュ中であるかの確認
    
    5. リフレッシュの現在のフェーズの確認
       5.1 未処理の伝播のチェック
       5.2 未処理のパージのチェック
       5.3 リフレッシュのサブフェーズのチェック
            5.3.1 SETUP サブブフェーズのチェック
            5.3.2 INSTANIATION サブフェーズのチェック
            5.3.3 WRAPUP サブフェーズのチェック
    
    6. リフレッシュが停止しているのかゆっくり実行されているのかを確認する手順
    
    
    各項の説明:
    
    1. リフレッシュ・プロセスの概要
    ===============================
    リフレッシュ・プロセスの詳細は、Document 1736065.1(KROWN:121393) で説明されています。 
    リフレッシュ・プロセスを簡潔に表現すると、リフレッシュでは MVIEW とプライマリ表が同期化されます。
    更新可能な MVIEW では、リフレッシュの push_deferred_rpc パラメータが TRUE の場合、まず MVIEW サイトの変更がプライマリ・サイトに伝播されます。
    次に、プライマリ・サイトから変更が取得されます。
    プライマリからの行の取得は、プライマリ表の MVIEW ログを使用して実行(高速リフレッシュ)することも、MVIEWログを使用せずに実行(完全リフレッシュ)することもできます。
    
    2. 現在リフレッシュが実行中であるかどうかの確認
    ===============================================
    MVIEW が単独でリフレッシュされているのか、リフレッシュ・グループの一部としてリフレッシュされているのかを確認しなければならない場合があります。
    次の各項では、この確認方法を説明します。
    この後の各項では、リフレッシュが実行されているセッションの SID を使用してさらに詳細な分析を行います。
    
    2.1 特定のMVIEWがリフレッシュ中であるかどうかの確認
    ===================================================
    これを確認するには、V$LOCK で該当の MVIEW に関して取得された JI タイプのロックがあるかどうかを調べます。
    
       column owner format a15
       column username format a15
       column mview format a15
       select o.owner, o.object_name mview, username, s.sid
       from v$lock l, dba_objects o, v$session s
       where o.object_id=l.id1 and
             l.type='JI' and
             l.lmode=6   and
             s.sid=l.sid and
             o.object_type='TABLE';
    
    
       OWNER           MVIEW           USERNAME               SID
       --------------- --------------- --------------- ----------
       <USER>           <MVIEWNAME1>            <USER>                   16
    
    
    * 以降、特に明記がない場合には SQL の実行は MVIEW サイトを想定しているものとします。
    
    2.2 リフレッシュ・グループがリフレッシュ中であるかどうかの確認
    ==============================================================
    リフレッシュ・グループのリフレッシュには、次の2つの方法があります。
    
      - バックグラウンドのジョブ・キュー・プロセスによってリフレッシュが実行される。
      - SQL*Plusなどのツール内でリフレッシュが手動で実行される。
    
    リフレッシュ・グループの名前と所有者がわかれば、次の問合せを使用して、ジョブ・キュー・プロセスによってリフレッシュが実行されているかどうかを確認できます。
    
       select s.sid, s.username
       from dba_jobs_running jr, v$session s, dba_jobs j
       where jr.sid=s.sid and
             j.job=jr.job and
             upper(j.what) like '%REFRESH%<リフレッシュ・グループの名前>%';
    
              SID USERNAME
       ---------- ---------------
               16 <USER>
    
    
    リフレッシュが手動で実行されているかどうかの確認は、多少複雑です。
    
    最初に sys.rgroup$ の該当する行のロックが取得されますが、このロックは解放されます。
    その後、リフレッシュ・グループの MVIEW ごとに1つずつ JI タイプのロックが取得されます。
    このことにより、リフレッシュが実行中であるかどうかを知ることができます。 
    
       column rowner format a15
       column rname  format a15
       column sid    format 9999
       select username, sid, rowner, rname
       from ( select username, s.sid, rc.rowner, rc.rname, count(*)
              from v$lock l, dba_objects o, v$session s, 
                   dba_refresh_children rc
              where o.object_id=l.id1 and
                    l.type='JI' and
                    l.lmode=6 and
                    s.sid=l.sid and
                    o.object_type='TABLE' and
                    o.object_name=rc.name and
                    o.owner=rc.owner and
                    rc.type='SNAPSHOT'
              group by username, s.sid, rc.rowner, rc.rname
              having count(*)=( select count(*) from dba_refresh_children
                                where rowner= rc.rowner and rname=rc.rname and
                                      type='SNAPSHOT') );
    
    
       USERNAME          SID ROWNER          RNAME
       --------------- ----- --------------- ---------------
       <USER>              16 <USER>          <MVIEWNAME1> 
    
    
    3. 前回および次回のリフレッシュ日の確認
    =======================================
    ジョブ・キュー・プロセスによって自動的にリフレッシュが実行されている場合や、手動で dbms_job.run() を実行してリフレッシュを実行している場合は、dba_jobs に次のような問合せを実行することにより、次回および前回のリフレッシュ時間を知ることができます。
    
       alter session set nls_date_format='dd-mm-yyyy hh24:mi:ss';
    
       column what format a36
       select what, last_date, next_date
       from dba_jobs
       where upper(what) like 'ÛMS_REFRESH.REFRESH(%<所有者>%.%<リフレッシュの名前>%';
    
       WHAT                       LAST_DATE           NEXT_DATE
       -------------------------- ------------------- -------------------
       dbms_refresh.refresh('"SCO 10-02-2003 10:48:46 11-02-2003 10:48:46
       TT"."R"'); 
    
    dbms_job によってリフレッシュが実行されていない場合でも、この問合せで次回の日付を確認することができます。
    ただし、前回のリフレッシュ日には正確な日付が示されません。
    この場合、前回のリフレッシュ日は、リフレッシュ・グループの各 MVIEW の dba_snapshot_refresh_times  * に問合せを行うことによって得ることができます。
    
       select rt.owner, rt.name, rt.last_refresh
       from dba_refresh_children rc, dba_snapshot_refresh_times rt
       where rc.owner=rt.owner and
             rc.name =rt.name  and
             rc.rname='<リフレッシュの名前>' and
             rc.owner='<リフレッシュ・グループの所有者>';
    
       OWNER           NAME                           LAST_REFRESH
       --------------- ------------------------------ -------------------
       <USER>           <MVIEWNAME1>                           10-02-2003 10:41:19
       <USER>            <MVIEWNAME2>                          10-02-2003 10:41:19
    
    * dba_snapshot_refresh_times は 9.0.1 以降 dba_mview_refresh_times に置き換わっています。
    
    4. リフレッシュ・グループのどの MVIEW がリフレッシュ中であるかの確認
    ==================================================================
    Oracle9i 以降のバージョンでは、V$MVREFRESH ビューを使用して、どの MVIEW がリフレッシュされているかを確認できます。
    次の問合せを使用して MVIEW を確認することができます。
    
       select currmvowner, currmvname
       from v$mvrefresh
       where sid=<第2.2項で確認したSID>;
    
    Oracle9iより前のバージョンでは、現在リフレッシュされている MVIEW の確認方法はこれより複雑になります。
    診断対象のリフレッシュが Instaniation フェーズである場合は、次の問合せで返される sql_text 文字列の FROM 句の object_name を使用して、現在リフレッシュ中の MVIEW を確認することができます。
    
       select sql_text
       from v$session ses, v$sqlarea sql
       where ses.sql_hash_value = sql.hash_value(+) and
             ses.sql_address = sql.address(+) and
             ses.sid=<第2.1項で確認したSID >;
    
    ただし、リフレッシュが SETUP または WRAPUP フェーズである場合は、プライマリ・サイトの対応するセッションを最初に確認する必要があります。
    これには、v$session の username、machine、logon_time の各列を選択してプライマリ・サイトでのセッションを見つけます。 
    
    プライマリ・サイトでのセッションの SID がわかれば、前述の問合せを使用して、SETUP または WRAPUP フェーズの MVIEW を確認することができます。
    
    
    5. リフレッシュの現在のフェーズの確認
    =====================================
    リフレッシュの現在のフェーズを確認しなければならない場合があります。
    
    リフレッシュを実行しているセッションの SID がわかれば、次の手順に従ってリフレッシュの現在のフェーズを確認することができます。
    
    5.1 未処理の伝播のチェック
    --------------------------
    リフレッシュの最初の手順は、push_deferred_rpc パラメータが TRUE の場合に遅延トランザクションをプッシュすることです。
    プッシュは、セッションによって割り当てられたロックを調べることによって追跡できます。
    プッシュとパージのフェーズが終了すると、これらのロックは解放されることに注意してください。
    
       column sid format 9999
       column state format a26
       select l.sid, 
              decode( count(*), 0, 'No propagation in progress', 
                                   'Propagation in progress' ) State
       from v$lock l, dbms_lock_allocated la
       where l.type='UL' and 
             l.lmode=4 and
             l.id1=la.lockid and
             la.name='ORA$DEF$EXE$PushCommonLock'
       group by l.sid;
    
         SID STATE
       ----- --------------------------
          16 Propagation in progress
    
    伝播のターゲット・サイトの確認には、次の問合せが役立ちます。
    
       column sid format 9999
    
       select l.sid, 'Currently propagating to ' || substr(la.name, 13)
       from v$lock l, dbms_lock_allocated la
       where l.type='UL' and 
             l.lmode=6 and
             l.id1=la.lockid and
             la.name like 'ORA$DEF$EXE$%';
    
    また、Oracle9 で並列伝播が実行されている場合は、次のようにします。
    
       select sid, 'Currently propagating to ' || dblink
       from v$replprop;
    
    
    5.2 未処理のパージのチェック
    ----------------------------
    遅延トランザクションのプッシュ後、リフレッシュの次の手順は伝播されたトランザクションのパージになります(リフレッシュが purge_option>0 および parallelism>0 で起動されている場合)。
    
       column sid format 9999
    
       select l.sid, 
              decode( count(*), 0, 'No purge in progress', 
                                   'Purge is in progress' ) State
       from v$lock l, dbms_lock_allocated la
       where l.type='UL' and 
             l.lmode=6 and
             l.id1=la.lockid and
             la.name='ORA$DEF$EXE$PurgeCommonLock'
       group by l.sid;
    
         SID STATE
       ----- --------------------
          16 Purge is in progress
    
    
    5.3 リフレッシュのサブフェーズのチェック
    ----------------------------------------
    遅延トランザクションのプッシュとパージが終わると、リフレッシュ処理はそのまま続行されます。
    リフレッシュは、SETUP、INSTATNIATION 及び WRAPUP の3つのフェーズで実行されます。
    
    
    Oracle9iでは、次の内容を簡単に確認できます。
      - 進行中のリフレッシュのタイプ
      - 進行中のリフレッシュのフェーズ
      - リフレッシュによって実行されたDMLの数
    
    次の問合せを使用して、これらを確認することができます。
    
       connect / as sysdba
       column "MVIEW BEING REFRESHED" format a30
       column INSERTS format 9999999
       column UPDATES format 9999999
       column DELETES format 9999999
       select  CURRMVOWNER_KNSTMVR || '.' || CURRMVNAME_KNSTMVR 
                   "MVIEW BEING REFRESHED",
               decode( REFTYPE_KNSTMVR, 1, 'FAST', 
    2, 'COMPLETE', 'UNKNOWN' ) REFTYPE,
               decode(GROUPSTATE_KNSTMVR, 1, 'SETUP', 2, 'INSTANTIATE', 
                                          3, 'WRAPUP', 'UNKNOWN' ) STATE,
               TOTAL_INSERTS_KNSTMVR INSERTS,
               TOTAL_UPDATES_KNSTMVR UPDATES,
               TOTAL_DELETES_KNSTMVR DELETES
       from X$KNSTMVR X
       WHERE type_knst=6 and 
             exists (select 1 from v$session s 
                     where s.sid=x.sid_knst and 
                           s.serial#=x.serial_knst);
    
    
    Oracle9iより前のバージョンでは、リフレッシュのフェーズの確認はこれより複雑になります。
    リフレッシュがどのサブフェーズにあるかの確認には、次の問合せの結果を使用できます。
    
       column sql_text format a77
    
       select sql_text
       from v$session ses, v$sqlarea sql
       where ses.sql_hash_value = sql.hash_value(+) and
             ses.sql_address = sql.address(+) and
             ses.sid=<第2.1項で確認したSID>;
    
    この問合せの結果を使用して、リフレッシュが SETUP、WRAPUP、INSTANTIATION のどのフェーズにあるかを確認することができます。
    次の各項でその手順を説明します。
    
    
    5.3.1 SETUP サブブフェーズのチェック
    --------------------------------------
    前述の問合せの結果を確認します。
    
       SQL_TEXT
       ------------------------------------------------------------------
       begin   sys.dbms_snapshot_utl.set_up   (:mown_col, :mas_c
       ol,:masobj_col, :rollseg_col,    :flag_col, :snaptime_col, :loadertim e_col, :
       num_sid, :snapid_tab,    :su_scn_col, :nr_flag);  end;
    
    
    出力に、sys.dbms_snapshot_utl.set_up@が含まれる場合、リフレッシュは
    SETUPフェーズです。 
    
    
    5.3.2 INSTANIATION サブフェーズのチェック
    ------------------------------------------
    SETUP の次のフェーズは、インスタンス化です。このフェーズでは、MVIEW の実表およびディクショナリ表に対して複数の文が実行されます。
    そのため、INSTANTIATION フェーズの確認にはいくつかの操作が必要になります。
    v$sqlarea からの sql_text に次の文のいずれかが表示される場合は、リフレッシュがプライマリサイトから行を取得していると考えられます。
    
       - SELECT /*+ remote_mapped( ...
       - UPDATE "OWNER"."MVIEWNAME" ...
       - INSERT INTO "OWNER"."MVIEWNAME" ...
       - UPDATE sys.snap$ SET status = :1, rscn = :2, refhnt = :3, flag = :4 
         WHERE vname = :5 AND sowner = :6 AND instsite = :7
       - UPDATE sys.snap_reftime$ SET snaptime = :1, loadertime = :2, refscn = :3, 
                fcmaskvec = :4, ejmaskvec = :5 
         WHERE sowner = :6 AND vname = :7 AND tablenum = :8 AND instsite = :9
    
    また、セッションがプッシュやパージを実行しておらず、SETUP フェーズでも WRAPUP フェーズでもないという事実が確認された場合は、リフレッシュがプライマリ・サイトから行を取得中であると考えることができ、このことから INSTANTIATION フェーズであると判断することもできます。
    
    
    5.3.3 WRAPUP サブフェーズのチェック
    ----------------------------------------
    出力にsys.dbms_snapshot_utl.wrap_up@が含まれる場合、リフレッシュは WRAPUPフェーズです。このフェーズのサンプル出力を次に示します。
    
    SQL_TEXT
    ------------------------------------------------------------------
    begin   sys.dbms_snapshot_utl.wrap_up@<HOST.DOMAIN>   (:snapid_col, :sn
    aptype_col, :masindx_col,    :mow_col, :mas_col, :masobj_col, :rollseg_col, :
    flag_col,    :snaptime_col, :loadertime_col);  end;
    
    
    6. リフレッシュが停止しているのかゆっくり実行されているのかを確認する手順
    =========================================================================
    リフレッシュのフェーズがわかれば、リフレッシュが停止しているのか、またはゆっくり実行されているのかを簡単に確認することができます。
    第5.3項で説明した問合せをここでも使用できます。
    
    リフレッシュが伝播フェーズの場合は、Document 1716114.1(KROWN:46038) の手順にて伝播を診断することができます。
    
    リフレッシュがある程度長い時間(たとえば数分)にわたって SETUP フェーズのままである場合は、プライマリ・サイトの対応するセッションで、リフレッシュが待機状態になる特別なイベントがないかを調べる必要があります。
    リフレッシュがエンキュー待ちになっている場合は、ブロックしているセッションを調べ、実行している内容を確認する必要があります。
    調べた内容に基づいて、ブロックしているセッションを終了しても望ましくない結果が発生しないことがわかれば、そのセッションを終了することができます。
    
    
    以下の問合せを使用すると、プライマリ・サイトで SETUP フェーズをブロックしているセッションを確認することができます。
    
       column holder format 99999
       column holder_name format a16
       column rowno format 9999999999
       column object_name format a25
       column owner format a16
    
       select w.holding_session holder,
              h.username holder_name,
              s.row_wait_row# rowno,
              o.object_name,
              o.owner
       from dba_waiters w, dba_objects o, v$session s, v$session h
       where w.waiting_session = s.sid
       and   w.holding_session = h.sid
       and   s.row_wait_obj# = o.object_id;
    
    
    SETUP フェーズの場合と同様に、WRAPUP フェーズのリフレッシュの診断でも、プライマリ・サイトの対応するセッションを調べる必要があります。
    はじめに、v$session_wait に問合せを実行して、待機イベントを確認します。
    
       select event, p1, p2, p3
       from v$session_wait
       where sid=<プライマリ・サイトのセッションのSID>;
    
    エンキュー・タイプの待機の場合は、ブロックしているセッションを確認します。
    このようなケースでは、WRAPUP フェーズをブロックしているセッションの中断によって停止が解決されるため、中断も検討してください。
    ただし、ブロックしているセッションによって望ましくない結果が発生しないかどうかをよく調べてください。
    
    WRAPUP 時の最も一般的なイベントは、データベース・ファイルの "db file scattered read" と "db file sequential read" です。 
    この問合せを連続して実行することにより、WRAPUP フェーズの進行状況をつかむことができます。
    P1 と P2 に表示される値は実行のたびに変わります。
    イベントが I/O 関連である場合は、次の問合せでこれらの値を使用して、アクセスされているオブジェクトを確認することができます。
    
       select owner, segment_name
       from dba_extents
       where file_id= and
              between block_id and block_id+blocks-1;
       
    
    INSTANTIATION フェーズでは、プライマリ・サイトから行が取得されます。
    このフェーズの診断では、最初に MVIEW サイトで次の問合せを実行します。 
    
       select event, p1, p2, p3
       from v$session_wait
       where sid=<セッションのSID>;
    
    これにより、リフレッシュの進行について初期的な情報を得ることができます。
    エンキュー・タイプの待機の場合は、ブロックしているセッションを前述の手順で確認できます。
    待機されているイベントが一貫して"SQL*Net message from dblink"である場合は、プライマリ・サイトのセッションでその待機のタイプを確認する必要があります。
    
    
    本文書利用上のご注意
    ====================
    本文書は英語で提供されているDocument 258021.1(最終更新日: 2008年3月5日) を翻訳したものです。
    ご利用に際しては、英語の原文を併せてご参照頂くことをお勧めいたします。
    
    
    [参照情報]
    Document 1736065.1(KROWN:121393)「マテリアライズド・ビューのリフレッシュ時に取得されるロックの動作について」
    Document 1749539.1(KROWN:142017)「マテリアライズド・ビューのリフレッシュの遅延、ハング時のトラブルシューティング・ガイド」
    Document 1716114.1(KROWN:46038)「レプリケーションが伝播した事を確認する方法、及び伝播しない場合のトラブルシューティング」
    Document 236233.1「Materialized View Refresh : Log Population and Purge」