th0x4c 備忘録

[Oracle] マテリアライズド・ビューの高速リフレッシュ

目的

集計(AVG(sal) など)や結合(emp.deptno = dept.deptno など)を含むマテリアライズド・ビューを高速リフレッシュ可能にする。

環境

  • OS: Oracle Enterprise Linux 5.8
  • DB: Oracle Database 11g Release 2 (11.2.0.3)

マニュアル

集計を含むマテリアライズド・ビュー

集計(AVG(sal) など)を含むマテリアライズド・ビューを高速リフレッシュ可能にする。

マニュアルから、集計関数(SUM, COUNT(*), AVG など)を含むマテリアライズド・ビューを高速リフレッシュ可能にするためにはいくつか制限がある。 ざっくり含める必要がある要件をまとめると以下。

  • マテリアライズド・ビュー・ログの要件

    • マテリアライズド・ビューで参照される列をすべて含める
    • ROWID および INCLUDING NEW VALUES 句を指定
    • 表の更新を行う場合は SEQUENCE 句を指定
  • マテリアライズド・ビューの SELECT 文に含める要件

例えば以下の SELECT を含むマテリアライズド・ビューを考える。

SELECT d.dname, AVG(e.sal) avg_sal
FROM emp e, dept d
WHERE e.deptno = d.deptno
GROUP BY d.dname;

高速リフレッシュ可能なマテリアライズド・ビューを作成する。

  • マテリアライズド・ビュー・ログの作成

CREATE MATERIALIZED VIEW LOG 文を実行

SQL> CREATE MATERIALIZED VIEW LOG ON emp
     WITH SEQUENCE, ROWID
     (sal, deptno)
     INCLUDING NEW VALUES;

Materialized view log created.

SQL> CREATE MATERIALIZED VIEW LOG ON dept
     WITH SEQUENCE, ROWID
     (deptno, dname)
     INCLUDING NEW VALUES;

Materialized view log created.
  • マテリアライズド・ビューの作成

CREATE MATERIALIZED VIEW 文を実行

SQL> CREATE MATERIALIZED VIEW emp_dept_mv
     BUILD IMMEDIATE
     REFRESH FAST
     ENABLE QUERY REWRITE
     AS SELECT d.dname, AVG(e.sal) avg_sal,
               COUNT(*) cnt, COUNT(e.sal) cnt_sal, SUM(e.sal) sum_sal
     FROM emp e, dept d
     WHERE e.deptno = d.deptno
     GROUP BY d.dname;

Materialized view created.

高速リフレッシュ可能か確認する方法

DBMS_MVIEW.EXPLAIN_MVIEW プロシージャを使用することで簡単にマテリアライズド・ビューに関して次のことを確認できる。

  • 高速リフレッシュ可能かどうか
  • 実行できるクエリー・リライトのタイプ
  • PCT リフレッシュ(パーティション単位での高速リフレッシュ)が可能かどうか(パーティション表でないと意味なし)

使い方は以下

  1. $ORACLE_HOME/rdbms/admin/utlxmv.sql を流して MV_CAPABILITIES_TABLE 表を作成
  2. DBMS_MVIEW.EXPLAIN_MVIEW プロシージャの引数にマテリアライズド・ビュー名かマテリアライズド・ビューで使用している SELECT 文を与えて実行
  3. MV_CAPABILITIES_TABLE 表を SELECT して確認
  4. 再度 DBMS_MVIEW.EXPLAIN_MVIEW プロシージャを実行する場合は TRUNCATE TABLE MV_CAPABILITIES_TABLE で結果をクリア

先ほど作成したマテリアライズド・ビューで確認してみる。

SQL> @?/rdbms/admin/utlxmv.sql

Table created.

SQL> EXEC DBMS_MVIEW.EXPLAIN_MVIEW('emp_dept_mv');

PL/SQL procedure successfully completed.

SQL> set lines 200
     set pages 100
     col capability_name for a30
     col rel_text for a10
     col msgtxt for a60
SQL> SELECT capability_name,  possible, SUBSTR(related_text,1,8)
       AS rel_text, SUBSTR(msgtxt,1,60) AS msgtxt
     FROM MV_CAPABILITIES_TABLE
     ORDER BY seq;

CAPABILITY_NAME                POS REL_TEXT   MSGTXT
------------------------------ --- ---------- ------------------------------------------------------------
PCT                            N
REFRESH_COMPLETE               Y
REFRESH_FAST                   Y
REWRITE                        Y
PCT_TABLE                      N   EMP        relation is not a partitioned table
PCT_TABLE                      N   DEPT       relation is not a partitioned table
REFRESH_FAST_AFTER_INSERT      Y
REFRESH_FAST_AFTER_ONETAB_DML  Y
REFRESH_FAST_AFTER_ANY_DML     Y
REFRESH_FAST_PCT               N              PCT is not possible on any of the detail tables in the mater
REWRITE_FULL_TEXT_MATCH        Y
REWRITE_PARTIAL_TEXT_MATCH     Y
REWRITE_GENERAL                Y
REWRITE_PCT                    N              general rewrite is not possible or PCT is not possible on an
PCT_TABLE_REWRITE              N   EMP        relation is not a partitioned table
PCT_TABLE_REWRITE              N   DEPT       relation is not a partitioned table

16 rows selected.

possible 列が Y であることから高速リフレッシュ可能であることが分かる。(PCT* に関してはパーティション表ではないので無視)

例えば、以下のようにマテリアライズド・ビュー作成前に高速リフレッシュ可能か確認でき、可能でない場合は理由を表示してくれる。

SQL> TRUNCATE TABLE MV_CAPABILITIES_TABLE;

Table truncated.

SQL> -- わざと COUNT(e.sal), SUM(e.sal) を外してみる
SQL> BEGIN
       DBMS_MVIEW.EXPLAIN_MVIEW('
         SELECT d.dname, AVG(e.sal) avg_sal,
                COUNT(*) cnt
         FROM emp e, dept d
         WHERE e.deptno = d.deptno
         GROUP BY d.dname');
     END;
     /

PL/SQL procedure successfully completed.

SQL> SELECT capability_name,  possible, SUBSTR(related_text,1,8)
       AS rel_text, SUBSTR(msgtxt,1,60) AS msgtxt
     FROM MV_CAPABILITIES_TABLE
     ORDER BY seq;

CAPABILITY_NAME                POS REL_TEXT   MSGTXT
------------------------------ --- ---------- ------------------------------------------------------------
PCT                            N
REFRESH_COMPLETE               Y
REFRESH_FAST                   N
REWRITE                        Y
PCT_TABLE                      N   EMP        relation is not a partitioned table
PCT_TABLE                      N   DEPT       relation is not a partitioned table
REFRESH_FAST_AFTER_INSERT      N   AVG_SAL    agg(expr) requires correspondng COUNT(expr) function
REFRESH_FAST_AFTER_ONETAB_DML  N              see the reason why REFRESH_FAST_AFTER_INSERT is disabled
REFRESH_FAST_AFTER_ANY_DML     N              see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled
REFRESH_FAST_PCT               N              PCT is not possible on any of the detail tables in the mater
REWRITE_FULL_TEXT_MATCH        Y
REWRITE_PARTIAL_TEXT_MATCH     Y
REWRITE_GENERAL                Y
REWRITE_PCT                    N              general rewrite is not possible or PCT is not possible on an
PCT_TABLE_REWRITE              N   EMP        relation is not a partitioned table
PCT_TABLE_REWRITE              N   DEPT       relation is not a partitioned table

16 rows selected.

高速リフレッシュが不可で、AVG_SAL 列に関して対応する COUNT(expr) が必要なことを指摘してくれる。

結合のみを含むマテリアライズド・ビュー

集計関数は含まずに結合(emp.deptno = dept.deptno など)のみを含むマテリアライズド・ビューを高速リフレッシュ可能にする。

マニュアルから、結合のみを含むマテリアライズド・ビューを高速リフレッシュ可能にするためにはいくつか制限がある。 ざっくり含める必要がある要件をまとめると以下。

  • マテリアライズド・ビュー・ログの要件

    • ROWID 句を指定
  • マテリアライズド・ビューの SELECT 文に含める要件

    • FROM 内の全ての表の ROWID を含める

例えば以下の SELECT を含むマテリアライズド・ビューを考える。

SELECT e.ename, d.loc
FROM emp e, dept d
WHERE e.deptno = d.deptno;

高速リフレッシュ可能なマテリアライズド・ビューを作成する。

  • マテリアライズド・ビュー・ログの作成

CREATE MATERIALIZED VIEW LOG 文を実行

SQL> CREATE MATERIALIZED VIEW LOG ON emp
     WITH ROWID;

Materialized view log created.

SQL> CREATE MATERIALIZED VIEW LOG ON dept
     WITH ROWID;

Materialized view log created.
  • マテリアライズド・ビューの作成

CREATE MATERIALIZED VIEW 文を実行

SQL> CREATE MATERIALIZED VIEW emp_dept_mv
     BUILD IMMEDIATE
     REFRESH FAST
     ENABLE QUERY REWRITE
     AS SELECT e.ename, d.loc,
               e.rowid e_rowid, d.rowid d_rowid
     FROM emp e, dept d
     WHERE e.deptno = d.deptno;

Materialized view created.
  • 高速リフレッシュ可能か確認

先ほど行ったように DBMS_MVIEW.EXPLAIN_MVIEW プロシージャで確認する。

SQL> TRUNCATE TABLE MV_CAPABILITIES_TABLE;

Table truncated.

SQL> EXEC DBMS_MVIEW.EXPLAIN_MVIEW('emp_dept_mv');

PL/SQL procedure successfully completed.

SQL> SELECT capability_name,  possible, SUBSTR(related_text,1,8)
       AS rel_text, SUBSTR(msgtxt,1,60) AS msgtxt
     FROM MV_CAPABILITIES_TABLE
     ORDER BY seq;

CAPABILITY_NAME                POS REL_TEXT   MSGTXT
------------------------------ --- ---------- ------------------------------------------------------------
PCT                            N
REFRESH_COMPLETE               Y
REFRESH_FAST                   Y
REWRITE                        Y
PCT_TABLE                      N   EMP        relation is not a partitioned table
PCT_TABLE                      N   DEPT       relation is not a partitioned table
REFRESH_FAST_AFTER_INSERT      Y
REFRESH_FAST_AFTER_ONETAB_DML  Y
REFRESH_FAST_AFTER_ANY_DML     Y
REFRESH_FAST_PCT               N              PCT is not possible on any of the detail tables in the mater
REWRITE_FULL_TEXT_MATCH        Y
REWRITE_PARTIAL_TEXT_MATCH     Y
REWRITE_GENERAL                Y
REWRITE_PCT                    N              general rewrite is not possible or PCT is not possible on an
PCT_TABLE_REWRITE              N   EMP        relation is not a partitioned table
PCT_TABLE_REWRITE              N   DEPT       relation is not a partitioned table

16 rows selected.

PCT* 以外は possible 列が Y になっているので高速リフレッシュ可能。

[Oracle] Data Guard ファスト・スタート・フェイルオーバー

目的

Data Guard のファスト・スタート・フェイルオーバーにより、プライマリ DB での障害発生時に自動でフェイルオーバーするようにする。

環境

  • OS: Oracle Enterprise Linux 5.8
  • DB: Oracle Database 11g Release 2 (11.2.0.3)
  • EM: Oracle Enterprise Manager Grid Control 11g (11.1)

ファスト・スタート・フェイルオーバーの構成

Data Guard のファスト・スタート・フェイルオーバーにより、プライマリ DB での障害発生時に自動でフェイルオーバーするようにできる。 ファスト・スタート・フェイルオーバーには、プライマリ DB、スタンバイ DB を監視する”オブザーバ”が必要。オブザーバはプライマリ DB、スタンバイ DB とは別のサーバに配置することが望ましいが、今回はスタンバイ DB と同じサーバに構成する。

EM Grid Control を使用してファスト・スタート・フェイルオーバーを有効にする。

  • プライマリ DB インスタンスの “可用性” タブ内の Data Guard の項目から “設定および管理” をクリックして、Data Guard のページを開く

  • “ファスト・スタート・フェイルオーバー” の “無効” をクリック

  • “オブザーバの構成” をクリック

  • オブザーバの場所として今回はスタンバイ DB と同じサーバを指定。ORACLE_HOME の位置も入力する。

  • “続行”

  • オブザーバを起動する OS ユーザを入力

  • “続行”

  • “はい”

  • 処理中 –> 完了

なぜか上記画面のまま “概要” のページに戻らない。alert.log を確認して処理が終わっていそうだったら、EM の画面を切り替えてしまってよい。

  • Data Guard の構成画面に戻ると “ファスト・スタート・フェイルオーバー” が “stdby1.localに対して有効” になり、”オブザーバの場所” が “sv2.local” になっている。(stdby1.local はスタンバイ DB, sv2.local はオブザーバを構成したサーバで今回はスタンバイ DB と同じサーバ)

ファスト・スタート・フェイルオーバーの検証

ファスト・スタート・フェイルオーバーが動作するか検証してみる。 マニュアル Data Guard Broker によると次の場合にファスト・スタート・フェイルオーバーが試行される。

  • プライマリ・データベースと、オブザーバおよびターゲット・スタンバイ・データベースの両方との接続が失われた場合
  • インスタンス障害
  • 強制終了(ABORT オプションでの停止)

正常にデータベースを停止した場合(NORMAL, IMMEDIATE, TRANSACTIONAL)では、ファスト・スタート・フェイルオーバーは試行されないので、プライマリ DB を停止するときは通常通り ABORT 以外のオプションで SHUTDOWN すればいい。

ファスト・スタート・フェイルオーバーを検証するためにプライマリ DB を shutdown abort で強制終了する。

# プライマリ側で実施
$ export ORACLE_SID=PROD1
$ sqlplus '/as sysdba'
SQL> shutdown abort
ORACLE instance shut down.

これで、プライマリ DB の異常をオブザーバが検知して、フェイルオーバーが自動で開始される。 オブザーバは Data Guard Broker の dgmgrl コマンドで実行されているので、ログは $ORACLE_HOME/rdbms/log/dgmgrl_XXXX_XXXX.log に出力されている。

# オブザーバ配置サーバで実施
$ ps -ef | grep dgmgrl
oracle   12805     1  0 20:27 ?        00:00:01 /u01/app/oracle/product/11.2.0/dbhome_1/bin/dgmgrl -logfile /u01/app/oracle/product/11.2.0/dbhome_1/rdbms/log/dgmgrl_PROD1_12804.log

$ cat $ORACLE_HOME/rdbms/log/dgmgrl_PROD1_12804.log 
Observer started
[W000 09/11 20:27:30.89] Observer started.

21:07:33.37  2012年9月11日 Tuesday
Initiating Fast-Start Failover to database "stdby1"...
Performing failover NOW, please wait...
Failover succeeded, new primary is "stdby1"
21:07:35.66  2012年9月11日 Tuesday

これで、フェイルオーバーが実施された。EM の元スタンバイ DB 側を確認すると以下のようになっている。

この後、元プライマリ DB を起動すると、自動でスタンバイ DB として構成してくれる。

# 元プライマリ側で実施
$ export ORACLE_SID=PROD1
$ sqlplus '/as sysdba'
SQL> shutdown abort
ORACLE instance shut down.
SQL> startup
ORACLE instance started.

Total System Global Area  835104768 bytes
Fixed Size                  2232960 bytes
Variable Size             511708544 bytes
Database Buffers          314572800 bytes
Redo Buffers                6590464 bytes
Database mounted.
ORA-16649: possible failover to another database prevents this database from
being opened

オブザーバのログを確認すると、元プライマリ DB が新たにスタンバイ DB としてマウントされたログ出力がある。

# オブザーバ配置サーバで実施
$ cat $ORACLE_HOME/rdbms/log/dgmgrl_PROD1_12804.log 
21:18:47.02  2012年9月11日 Tuesday
Initiating reinstatement for database "PROD1"...
Reinstating database "PROD1", please wait...
Operation requires shutdown of instance "PROD1" on database "PROD1"
Shutting down instance "PROD1"...
ORA-01109: database not open

Database dismounted.
ORACLE instance shut down.
Operation requires startup of instance "PROD1" on database "PROD1"
Starting instance "PROD1"...
ORACLE instance started.
Database mounted.
Continuing to reinstate database "PROD1" ...
Reinstatement of database "PROD1" succeeded
21:19:33.19  2012年9月11日 Tuesday

EM の元スタンバイ DB 側を確認すると以下のように元プライマリ DB が新たにスタンバイ DB として構成されていることが分かる。

この後、スイッチオーバすれば、元の構成に戻る。

ファスト・スタート・フェイルオーバー環境でのデータベースの停止

マニュアル に記載があるように、ファスト・スタート・フェイルオーバー環境でのデータベースの停止する場合は次のようにする。

  1. オブザーバを停止し、プライマリ DB およびターゲット・スタンバイ DB の両方について、V$DATABASE.FS_FAILOVER_OBSERVER_PRESENT 列が NO になるまで待機する。こうすると、プライマリ DB の停止中に、ファスト・スタート・フェイルオーバーは実行されない。

  2. プライマリ DB およびターゲット・スタンバイ DB を停止(SHUTDOWN)する。

以下が実行例。

dgmgrl にてオブザーバを停止

$ export ORACLE_SID=stdby1
$ dgmgrl
DGMGRL for Linux: Version 11.2.0.3.0 - 64bit Production

Copyright (c) 2000, 2009, Oracle. All rights reserved.

Welcome to DGMGRL, type "help" for information.
DGMGRL> connect sys/oracle
Connected.
DGMGRL> stop observer;
Done.
DGMGRL> exit

プライマリ DB およびスタンバイ DB にてV$DATABASE.FS_FAILOVER_OBSERVER_PRESENT 列が NO になることを確認して SHUTDOWN する。

# プライマリ DB および スタンバイ DB でそれぞれ実施
$ sqlplus 'as sysdba'
SQL> SELECT FS_FAILOVER_OBSERVER_PRESENT FROM V$DATABASE;

FS_FAILOVER_OBSERVER_
---------------------
YES

SQL> /

FS_FAILOVER_OBSERVER_
---------------------
NO

SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> exit

起動時はプライマリ DB およびスタンバイ DB を起動した後に、dgmgrl でオブザーバを起動(start observer)する。

[Oracle] Data Guard 環境での RMAN の構成

目的

Data Guard 環境での RMAN のアーカイブ・ログ削除方針を変更する。

環境

  • OS: Oracle Enterprise Linux 5.8
  • DB: Oracle Database 11g Release 2 (11.2.0.3)

マニュアル

Data Guard 環境での RMAN の構成

Data Guard 環境での RMAN のアーカイブ・ログ削除方針を変更する。

  • 現在の設定の確認

プライマリ DB をターゲットとして接続し、show all コマンドで現在の設定を確認

$ export ORACLE_SID=PROD1
$ rman target /
RMAN> show all;

using target database control file instead of recovery catalog
RMAN configuration parameters for database with db_unique_name PROD1 are:
CONFIGURE RETENTION POLICY TO REDUNDANCY 1; # default
CONFIGURE BACKUP OPTIMIZATION OFF; # default
CONFIGURE DEFAULT DEVICE TYPE TO DISK; # default
CONFIGURE CONTROLFILE AUTOBACKUP OFF; # default
CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '%F'; # default
CONFIGURE DEVICE TYPE DISK PARALLELISM 1 BACKUP TYPE TO BACKUPSET; # default
CONFIGURE DATAFILE BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default
CONFIGURE ARCHIVELOG BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default
CONFIGURE MAXSETSIZE TO UNLIMITED; # default
CONFIGURE ENCRYPTION FOR DATABASE OFF; # default
CONFIGURE ENCRYPTION ALGORITHM 'AES128'; # default
CONFIGURE COMPRESSION ALGORITHM 'BASIC' AS OF RELEASE 'DEFAULT' OPTIMIZE FOR LOAD TRUE ; # default
CONFIGURE ARCHIVELOG DELETION POLICY TO NONE; # default
CONFIGURE SNAPSHOT CONTROLFILE NAME TO '/u01/app/oracle/product/11.2.0/dbhome_1/dbs/snapcf_PROD1.f'; # default

アーカイブ・ログの削除方針(CONFIGURE ARCHIVELOG DELETION POLICY)はデフォルトの NONE になっている。

  • アーカイブ・ログの削除方針を変更する。

CONFIGURE ARCHIVELOG DELETION POLICY コマンドによりアーカイブ・ログの削除方針を変更する。

すべてのスタンバイ DB への送信(SHIPPED)を確認するまでアーカイブ・ログを削除しないようにする場合は、次のようにする。

RMAN> CONFIGURE ARCHIVELOG DELETION POLICY TO SHIPPED TO ALL STANDBY;

new RMAN configuration parameters:
CONFIGURE ARCHIVELOG DELETION POLICY TO SHIPPED TO ALL STANDBY;
new RMAN configuration parameters are successfully stored

すべてのスタンバイ DB への適用(APPLIED)を確認するまでアーカイブ・ログを削除しないようにする場合は、次のようにする。

RMAN> CONFIGURE ARCHIVELOG DELETION POLICY TO APPLIED ON ALL STANDBY;

new RMAN configuration parameters:
CONFIGURE ARCHIVELOG DELETION POLICY TO APPLIED ON ALL STANDBY;
new RMAN configuration parameters are successfully stored