OCI BaseDBの19cから23cへのデータ移行(DataPump編) [OCI]

1.はじめに


 OCI上で19cから23cの環境へデータを移行する検証をしたので備忘までメモを残しておく。具体的なシナリオとしては、19cの環境でexpdpでエクスポートしたダンプファイルを、新規に23cの環境にimpdpでインポートする。ダンプファイルはノーマル(平文)と、TDEの暗号鍵で暗号化したもの(encryption_mode = transparent)の2種類を用いる。後者のインポートのために、19c環境のTDEのマスタ暗号鍵を23c環境へインポートすることも行う。

20231124_expimp23cTestEnv2.jpg

 手順の概要は以下の通り。

2.環境準備


・ソースDB


 データ移行の対象となる表の状態確認をする。EMP表100万件、DEPT表10万件、セグメントサイズは合計77MB程度である。
[oracle@oradbvm1 ~]$ sqlplus scott/XXX@oradb
SQL> select count(*) from emp;
  COUNT(*)
----------
   1000000

SQL> select count(*) from dept;
  COUNT(*)
----------
    100000
    
SQL>  select segment_name, bytes/1024/1024 mb from user_segments;
   SEGMENT_NAME    MB
_______________ _____
DEPT                5 ★
EMP                72 ★
IDX1_EMP           23
PK_DEPT             2
PK_EMP             16

SQL>

 Base Database Serviceでは/u01配下に150GB程度の領域がある。この配下にディレクトリオブジェクトを作成する。
[oracle@oradbvm1 ~]$ df -h
Filesystem                      Size  Used Avail Use% Mounted on
・・・
/dev/sdg                        196G   42G  145G  23% /u01 ★

[oracle@oradbvm1 ~]$ mkdir -p /u01/app/oracle/dump/scott
[oracle@oradbvm1 ~]$ chmod 777 /u01/app/oracle/dump/scott
[oracle@oradbvm1 ~]$ ls -ld /u01/app/oracle/dump/scott
drwxrwxrwx 2 oracle oinstall 4096 Nov 21 06:11 /u01/app/oracle/dump/scott

[oracle@oradbvm1 ~]$ sqlplus sys/XXX@oradb as sysdba
SQL> CREATE DIRECTORY expdir AS '/u01/app/oracle/dump/scott';
Directory created.
SQL> grant read, write on directory expdir to scott;
Grant succeeded.

・ターゲットDB


 OCIコンソールからソースDBと同じセグメントに新規インスタンスを作成する。この際、DBバージョンは23c、エディションはEE HPを選択する(詳細な手順については[1]を参照)。プロビジョニング完了後、以下設定を行う。
  • OSのoracleユーザのパスワードを設定する(sshのファイル転送のため)
  • tnsnames.oraにPDBへの接続エントリを追加する
  • ソースDBと同じスキーマ(scott)を作成、必要な権限を付与する

 ディレクトリオブジェクトの作成はソースと同じ手順を実施する。表はソース側のEMP・DEPT表のDDL(参考[2]参照)を実行する。

3.エクスポート


・(ソースDB)マスタ暗号鍵のエクスポート


 ソースDBのPDBの管理者で接続し、以下のようにマスタ暗号鍵をエクスポートする。
[oracle@oradbvm1 ~]$ sqlplus sys/XXX@oradb as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Wed Nov 22 09:21:03 2023
Version 19.20.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.

Connected to:
Oracle Database 19c EE High Perf Release 19.0.0.0.0 - Production
Version 19.20.0.0.0

SQL> administer key management export encryption keys with secret "XXX" to '/home/oracle/ewallet_oradbmv1_oradb.p12' force keystore identified by "XXX";

keystore altered.

SQL> !ls -l
total 6108
-rw-r--r-- 1 oracle asmadmin    2612 Nov 22 09:21 ewallet_oradbmv1_oradb.p12 ★
SQL> 

・(ソースDB)データのエクスポート


はじめにノーマル(平文)のエクスポートを実行する。平文でエクスポートされたことを示すORA-39173が出力されるが、処理は正常終了する。
[oracle@oradbvm1 scott]$ expdp scott/XXX@oradb schemas=scott directory=expdir dumpfile=scott.dmp logfile=expdpscott.log content=data_only

Export: Release 19.0.0.0.0 - Production on Sun Nov 12 16:20:46 2023
Version 19.20.0.0.0

Copyright (c) 1982, 2019, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 19c EE High Perf Release 19.0.0.0.0 - Production
FLASHBACK automatically enabled to preserve database integrity.
Starting "SCOTT"."SYS_EXPORT_SCHEMA_01":  scott/********@oradb schemas=scott directory=expdir dumpfile=scott.dmp logfile=expdpscott.log content=data_only
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
. . exported "SCOTT"."EMP"                               55.15 MB 1000000 rows
. . exported "SCOTT"."DEPT"                              3.619 MB  100000 rows ★=~59MB
ORA-39173: Encrypted data has been stored unencrypted in dump file set. ★暗号化されてない
Master table "SCOTT"."SYS_EXPORT_SCHEMA_01" successfully loaded/unloaded
******************************************************************************
Dump file set for SCOTT.SYS_EXPORT_SCHEMA_01 is:
  /u01/app/oracle/dump/scott/scott.dmp
Job "SCOTT"."SYS_EXPORT_SCHEMA_01" successfully completed at Sun Nov 12 16:20:51 2023 elapsed 0 00:00:04 ★正常終了

 続いて暗号化エクスポートを実行する。encryption=data_onlyと指定する。encryption_modeは指定していないが、TDEのウォレットがオープン状態なので、デフォルトでtransparent、つまりTDEのマスタ暗号鍵を利用して暗号化を行うこととなる。ORA-39173は発生しないので、暗号化されていることがわかる。
[oracle@oradbvm1 scott]$ expdp scott/XXX@oradb schemas=scott directory=expdir dumpfile=scotte.dmp logfile=expdpscotte.log content=data_only encryption=data_only

Export: Release 19.0.0.0.0 - Production on Sun Nov 12 16:52:47 2023
Version 19.20.0.0.0

Copyright (c) 1982, 2019, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 19c EE High Perf Release 19.0.0.0.0 - Production
FLASHBACK automatically enabled to preserve database integrity.
Starting "SCOTT"."SYS_EXPORT_SCHEMA_01":  scott/********@oradb schemas=scott directory=expdir dumpfile=scotte.dmp logfile=expdpscotte.log content=data_only encryption=data_only
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
. . exported "SCOTT"."EMP"                               55.15 MB 1000000 rows
. . exported "SCOTT"."DEPT"                              3.619 MB  100000 rows ★=~59MB
Master table "SCOTT"."SYS_EXPORT_SCHEMA_01" successfully loaded/unloaded
******************************************************************************
Dump file set for SCOTT.SYS_EXPORT_SCHEMA_01 is:
  /u01/app/oracle/dump/scott/scotte.dmp
Job "SCOTT"."SYS_EXPORT_SCHEMA_01" successfully completed at Sun Nov 12 16:52:52 2023 elapsed 0 00:00:04 ★正常終了

ディレクトリオブジェクトのファイルを確認すると、以下のように2つのダンプファイルが作成されていることがわかる。暗号化してもファイルサイズに変化はない。
[oracle@oradbvm1 scott]$ ll
total 120936
-rw-r--r-- 1 oracle asmadmin     1056 Nov 12 16:52 expdpscotte.log
-rw-r--r-- 1 oracle asmadmin     1104 Nov 12 16:48 expdpscott.log
-rw-r----- 1 oracle asmadmin 61911040 Nov 12 16:48 scott.dmp ★ノーマル(平文)
-rw-r----- 1 oracle asmadmin 61911040 Nov 12 16:52 scotte.dmp ★暗号化
[oracle@oradbvm1 scott]$

4.ダンプファイル転送


・マスタ暗号鍵の転送


 ソースDBからマスタ暗号鍵をscp転送する
[oracle@oradbvm1 ~]$ cd ~/
[oracle@oradbvm1 ~]$ scp ewallet_oradbmv1_oradb.p12 10.0.1.12:~/
oracle@10.0.1.12's password:
ewallet_oradbmv1_oradb.p12                    100% 2612     5.4MB/s   00:00

・ダンプファイルの転送


 ソースDBからダンプファイルをscp転送する。
[oracle@oradbvm1 ~]$ cd /u01/app/oracle/dump/scott
[oracle@oradbvm1 scott]$ scp *.dmp 10.0.1.12:/u01/app/oracle/dump/scott
oracle@10.0.1.12's password:
scott.dmp                                     100%   59MB 100.0MB/s   00:00
scotte.dmp                                    100%   59MB  98.0MB/s   00:00
[oracle@oradbvm1 scott]$

 ターゲットDBにて、ダンプファイルを確認する。
[oracle@oradbvm2 scott]$ ll
-rw-r----- 1 oracle oinstall  61911040 Nov 21 07:12 scott.dmp
-rw-r----- 1 oracle oinstall  61911040 Nov 21 07:12 scotte.dmp

5.インポート


・(ターゲットDB)データのインポート(ノーマル)


 ターゲットDBにて、インポートを行う。EMP表からDEPT表への参照整合性制約を無効にしてからインポートを行うと、問題なくインポートできる。
[oracle@oradbvm2 ~]$ sqlplus scott/XXX@oradb
SQL> alter table emp disable constraint fk_deptno;

[oracle@oradbvm2 ~]$ impdp scott/XXX@oradb schemas=scott directory=expdir dumpfile=scott.dmp logfile=impdpscott.log content=data_only table_exists_action=truncate

Import: Release 23.0.0.0.0 - Production on Fri Nov 24 09:55:25 2023
Version 23.3.0.23.09

Copyright (c) 1982, 2023, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 23c EE High Perf Release 23.0.0.0.0 - Production
Master table "SCOTT"."SYS_IMPORT_SCHEMA_01" successfully loaded/unloaded
Starting "SCOTT"."SYS_IMPORT_SCHEMA_01":  scott/********@oradb schemas=scott directory=expdir dumpfile=scott.dmp logfile=impdpscott.log content=data_only table_exists_action=truncate
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
. . imported "SCOTT"."EMP"                               55.15 MB 1000000 rows
. . imported "SCOTT"."DEPT"                              3.619 MB  100000 rows
Job "SCOTT"."SYS_IMPORT_SCHEMA_01" successfully completed at Fri Nov 24 09:56:09 2023 elapsed 0 00:00:35 ★成功

 ここで試しに、暗号化したダンプファイルをインポートしようとすると、複合化に必要なマスタ暗号鍵が見つからないため、ORA-28362のエラーでインポートすることができない。このため、ソースDBのPDBのマスタ暗号鍵のインポートが必要となる。
SQL> !impdp scott/XXX@oradb schemas=scott directory=expdir dumpfile=scotte.dmp logfile=impdpscotte.log content=data_only table_exists_action=truncate

Import: Release 23.0.0.0.0 - Production on Fri Nov 24 09:56:52 2023
Version 23.3.0.23.09

Copyright (c) 1982, 2023, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 23c EE High Perf Release 23.0.0.0.0 - Production
ORA-39002: invalid operation
ORA-39189: unable to decrypt dump file set
ORA-28362: master key not found ★エラーとなる

・(ターゲットDB)マスタ暗号鍵のインポート


 ターゲットDBにて、ソースDBのPDBのマスタ暗号鍵をインポートする。インポートはコンテナDBに接続して実行する(PDBではインポートできない)。v$encryption_keysでインポートされていることを確認する。
[oracle@oradbvm2 ~]$ ll
total 12
-rw-r--r-- 1 oracle oinstall 2612 Nov 22 09:22 ewallet_oradbmv1_oradb.p12 ★

[oracle@oradbvm2 ~]$ sqlplus / as sysdba

SQL*Plus: Release 23.0.0.0.0 - Production on Wed Nov 22 09:26:27 2023
Version 23.3.0.23.09

Copyright (c) 1982, 2023, Oracle.  All rights reserved.


Connected to:
Oracle Database 23c EE High Perf Release 23.0.0.0.0 - Production
Version 23.3.0.23.09

SQL> administer key management import keys with secret "XXX" from '/home/oracle/ewallet_oradbmv1_oradb.p12' force keystore identified by "XXX" with backup;

keystore altered.

SQL> select key_id, creation_time, creator_dbname, activating_pdbname, con_id from v$encryption_keys;

KEY_ID                                                  CREATION_TIME                             CREATOR_DBNAME     ACTIVATING_PDBNAME       CON_ID
_______________________________________________________ _________________________________________ __________________ _____________________ _________
AXTVRRDA8U+uv9W09+9PuAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA    19-APR-23 10.54.29.632286000 PM GMT       coradb_oradbvm1    ORADB                         3★PDBのマスタ暗号鍵
ARq4NDRE80+SvwxzekrKJbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA    23-NOV-23 05.20.41.789397000 PM -07:00    coradb_oradbvm2    CDB$ROOT                      1
AYpmGS1/Gk9Ev1QZZYcswd4AAAAAAAAAAAAAAAAAAAAAAAAAAAAA    23-NOV-23 05.27.18.895760000 PM -07:00    coradb_oradbvm2    ORADB                         3
SQL>

・(ターゲットDB)データのインポート(暗号化)


 暗号化されたダンプファイルをインポートする。正常にインポートされたら、参照整合性制約を有効にする。
[oracle@oradbvm2 ~]$ impdp scott/XXX@oradb schemas=scott directory=expdir dumpfile=scotte.dmp logfile=impdpscotte.log content=data_only table_exists_action=truncate

Import: Release 23.0.0.0.0 - Production on Fri Nov 24 10:15:06 2023
Version 23.3.0.23.09

Copyright (c) 1982, 2023, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 23c EE High Perf Release 23.0.0.0.0 - Production
Master table "SCOTT"."SYS_IMPORT_SCHEMA_01" successfully loaded/unloaded
Starting "SCOTT"."SYS_IMPORT_SCHEMA_01":  scott/********@oradb schemas=scott directory=expdir dumpfile=scotte.dmp logfile=impdpscotte.log content=data_only table_exists_action=truncate
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
. . imported "SCOTT"."EMP"                               55.15 MB 1000000 rows
. . imported "SCOTT"."DEPT"                              3.619 MB  100000 rows
Job "SCOTT"."SYS_IMPORT_SCHEMA_01" successfully completed at Fri Nov 24 10:15:32 2023 elapsed 0 00:00:24 ★成功

[oracle@oradbvm2 ~]$ sqlplus scott/XXX@oradb
SQL> alter table emp enable constraint fk_deptno;

6.まとめ


 本稿では、OCI上で19cの環境からデータをexpdp/impdpで23cの環境へ移行する手順について記載した。
 実際問題、今回のケースのようにOCIの内部でダンプの暗号化までする必要はないだろう。しかし、実際はファイルサイズが大きくなると、オブジェクトストレージや媒体を介した転送が必要なケースもあり、そのような場合に暗号化が必要になることが考えられる。暗号化の方法にはパスワードを設定する方法(encryption_mode=password)もあるが、インポートの際に毎回パスワードを設定するのも煩わしい。OCIでEE High Performance以上を使っているなら、advanced securityのダンプファイルの暗号化機能が利用できるため、元のPDBのマスタ暗号鍵をターゲットとなるDBにインポートすることで、透過的に暗号化ダンプファイルのエクスポート・インポートが可能となる。

参考


[1]ベースデータベース コンソールを使用したDBシステムの作成
https://docs.public.oneportal.content.oci.oraclecloud.com/ja-jp/iaas/dbcs/doc/create-db-system-using-console.html#DBSCB-GUID-624EFC8F-CF53-4A88-B9AB-2F45F2B9A546

[2]検証用DDL
drop table emp cascade constraints;
drop table dept cascade constraints;
create table dept(  
  deptno     number(7,0),  
  dname      varchar2(14),  
  loc        varchar2(13),  
  constraint pk_dept primary key (deptno)  
);
create table emp(  
  empno    number(7,0),  
  ename    varchar2(10),  
  job      varchar2(9),  
  mgr      number(7,0),  
  hiredate date,  
  sal      number(7,2),  
  comm     number(7,2),  
  deptno   number(7,0),  
  constraint pk_emp primary key (empno),  
  constraint fk_deptno foreign key (deptno) references dept (deptno)  
);
create index idx1_emp on emp ( deptno );


UNION ALLを使ったMVIEWの制約について [SQL・DDL]

1.はじめに


 最近、MVIEWでUNION ALLを使った場合の制約について調査したので、備忘までメモを残しておきたい。
 MVIEWとは実体のあるビューであり、ある断面のデータを複製してビューをあたかもローカルの表のようにして使う機能である。MVIEWは大規模なテーブルを集計する処理において、VIEW経由でアクセスされる度に計算するのではなく、あらかじめ集計結果を実体として保持しておくことにより、参照時に高価な処理を何度も行うことを回避できるメリットがある。
 ソースとなる表が更新されることにより、レプリカであるMVIEWの更新が必要となるが、高速リフレッシュという機能を使うことにより、ソース側表の更新履歴(MLOGという)だけをMVIEWに反映することがで、差分更新が可能である。
 高速リフレッシュが可能なクエリには制約がある。一般的に、結合や集計処理を含む複雑なクエリになるほど制約を意識する必要がある。また、MVIEWの定義にはDBLINKを利用できるため、(複数の)リモートDBからDBLINK経由でMVIEWを構成することができるが、これにも制約がある。実現したいビューがMVIEWで構成できるかどうかは、上記の複雑な制約の網をくぐり抜ける必要があるため、実機での確認がかかせない。
 ここでは、スキーマ分割された表(定義は同一)を別データベースにMVIEWで1つにUNION ALLでまとめて参照したい、という要件について、実機でMVIEW の実現可否や運用上の制約事項を調べてみよう。。

2.検証モデル


 検証のモデルとして、下図のような構成を考える。
  • PDBは2つ(k3,k5)でその間にリモートMVIEW用のDBLINK(k5tok3)を構成する
  • MVIEWのソースとなるPDB(k3)には3つのスキーマ(a,b,c)を作成し、それぞれemp表を作成する。データは主キーが重複しないように入れる
  • EMP表には、それぞれ高速リフレッシュ用のMLOGを作成する
  • MVIEWのターゲットであるPDB(k5)に3つのEMP表をUNION ALLしたMVIEWを作成する(MF_EMP_UNION)

20230514_MVIEWUNION.jpg

 この構成で特筆すべき点は2つある。1つはMLOGにROWIDを含めることである。ROWIDはソース表の行を特定する物理アドレスであり、これを更新ログに記録する。もう一つはMVIEWのカラム定義に、ROWIDとユニオンマーカ(ユニオンのソースとなる表を一位に特定するカラム)を含めることである。
 以下に、手元のVirtual BoxのOracle19.11の環境を用いて、このモデルを実際に作成してみよう。まず表を作成する。以下の表定義をソースのPDBの3つのスキーマで実行する。
drop table emp cascade constraints;
drop table dept cascade constraints;
create table dept(  
  deptno     number(7,0),  
  dname      varchar2(14),  
  loc        varchar2(13),  
  constraint pk_dept primary key (deptno)  
);
create table emp(  
  empno    number(7,0),  
  ename    varchar2(10),  
  job      varchar2(9),  
  mgr      number(7,0),  
  hiredate date,  
  sal      number(7,2),  
  comm     number(7,2),  
  deptno   number(7,0),  
  constraint pk_emp primary key (empno),  
  constraint fk_deptno foreign key (deptno) references dept (deptno)  
);
create index idx1_emp on emp ( deptno );

次にデータを挿入する。a、b、cのスキーマでempnoが100ずつずれるようにして挿入する。
conn b/b@k3
@creemp
insert into dept select
rownum+10 deptno,
dbms_random.string('u',14) dname,
dbms_random.string('u',13) loc
from dual connect by level <=10;
commit;
insert into emp select
rownum+100 empno,
dbms_random.string('u',10) ename,
dbms_random.string('u',9) job,
dbms_random.value(1,100)+100 mgr,
sysdate - dbms_random.value(1,5000) hiredate,
dbms_random.value(3000,9999) sal,
dbms_random.value(3000,9999) comm,
dbms_random.value(1,10)+10 deptno
from dual connect by level <=100;
commit;
exec dbms_stats.gather_table_stats('b','dept');
exec dbms_stats.gather_table_stats('b','emp');

conn c/c@k3
@creemp
insert into dept select
rownum+20 deptno,
dbms_random.string('u',14) dname,
dbms_random.string('u',13) loc
from dual connect by level <=10;
commit;
insert into emp select
rownum+200 empno,
dbms_random.string('u',10) ename,
dbms_random.string('u',9) job,
dbms_random.value(1,100)+200 mgr,
sysdate - dbms_random.value(1,5000) hiredate,
dbms_random.value(3000,9999) sal,
dbms_random.value(3000,9999) comm,
dbms_random.value(1,10)+20 deptno
from dual connect by level <=100;
commit;
exec dbms_stats.gather_table_stats('c','dept');
exec dbms_stats.gather_table_stats('c','emp');

 挿入された行を各表毎3行ずつサンプルで確認する。
SQL> select empno, ename from a.emp where rownum <= 3
  2  union all
  3  select empno, ename from b.emp where rownum <= 3
  4  union all
  5* select empno, ename from c.emp where rownum <= 3;

   EMPNO ENAME
________ _____________
       1 WANOZRAMAP
       2 GMREPEQFIN
       3 SKWBNXLCNF
     101 GVXUEOOQJM
     102 XGLASIZISR
     103 UVODELRDCI
     201 LKCFXEGPPE
     202 JKKFUPAHXM
     203 VGMJJTAVUN

9 rows selected.

 次にソース側PDB(k3)で各EMP表に対してMLOGを作成する。MLOGはROWIDを使って作成していることに留意する。
SQL> conn a/a@k3
Connected.

SQL> create materialized view log on emp with rowid including new values;

Materialized view log EMP created.

SQL> conn b/b@k3
Connected.

SQL> create materialized view log on emp with rowid including new values;

Materialized view log EMP created.

SQL> conn c/c@k3
Connected.

SQL> create materialized view log on emp with rowid including new values;

Materialized view log EMP created.

 以上でソース側の準備が完了したため、リモート側のPDB(k5)でMVIEWを作成する。高速リフレッシュを使うため、refresh fastを指定し、各selectのカラムにrowid列とユニオンマーカとなるmarker列を含めていることに留意する。
SQL> conn f/f@k5
Connected.
SQL> create materialized view mf_emp_union
  2  build immediate refresh fast on demand as
  3  select rowid "rowid", 1 marker, empno,ename,job,mgr,hiredate,sal,comm,deptno from a.emp@k5tok3
  4  union all
  5  select rowid "rowid", 2 marker, empno,ename,job,mgr,hiredate,sal,comm,deptno from b.emp@k5tok3
  6  union all
  7  select rowid "rowid", 3 marker, empno,ename,job,mgr,hiredate,sal,comm,deptno from c.emp@k5tok3
  8* ;
alter table mf_emp_union add constraint pk_mf_emp_union primary key (empno);

Materialized view MF_EMP_UNION created.

SQL> alter table mf_emp_union add constraint pk_mf_emp_union primary key (empno);

Table MF_EMP_UNION altered.

 MVIEWが作成され、同期されていることが確認する。
SQL> select empno,ename from mf_emp_union where empno in (1,2,3,101,102,103,201,202,203);

   EMPNO ENAME
________ _____________
       1 WANOZRAMAP
       2 GMREPEQFIN
       3 SKWBNXLCNF
     101 GVXUEOOQJM
     102 XGLASIZISR
     103 UVODELRDCI
     201 LKCFXEGPPE
     202 JKKFUPAHXM
     203 VGMJJTAVUN

9 rows selected.

 以上で準備は完了である。

3.検証


 ここでは以下3つのシナリオで高速リフレッシュの動作検証を行う。
 (1)c.EMPに全件UPDATE、c.EMPに1件INSERTを行い、高速リフレッシュ
 (2)c.EMPをalter table moveし、高速リフレッシュ
 (3)c.EMPをトランケートし、高速リフレッシュ
 期待される結果は、(1)は正常に同期される。(2)(3)は高速リフレッシュがエラーとなり、復旧に完全リフレッシュが必要となるはずである。以下、それぞれについて結果を確認していこう。

(1)c.EMPに全件UPDATE、c.EMPに1件INSERTを行い、高速リフレッシュ


 c.EMPにUPDATEと1件INSERTを行う。
SQL> conn c/c@k3
Connected.
SQL> update emp set ename='ZZZ';

100 rows updated.

SQL> commit;

Commit complete.

SQL> insert into emp values(997, 'KING', 'PRESIDENT', null,  sysdate, 5000, null, 21);

1 row inserted.

SQL> commit;

Commit complete.

 ターゲットPDB(k5)にて、高速リフレッシュを実行する。高速リフレッシュ後に、MVIEWに正しくenameの更新、および1件INSERTされたことが確認できる。
SQL> conn f/f@k5
Connected.
SQL> select empno,ename from mf_emp_union where empno in (1,2,3,101,102,103,201,202,203);

   EMPNO ENAME
________ _____________
       1 WANOZRAMAP
       2 GMREPEQFIN
       3 SKWBNXLCNF
     101 GVXUEOOQJM
     102 XGLASIZISR
     103 UVODELRDCI
     201 LKCFXEGPPE
     202 JKKFUPAHXM
     203 VGMJJTAVUN

9 rows selected.

SQL> select empno,ename from mf_emp_union where empno=997;

no rows selected
SQL> EXECUTE DBMS_MVIEW.REFRESH('mf_emp_union', 'f');

PL/SQL procedure successfully completed.

SQL> select empno,ename from mf_emp_union where empno in (1,2,3,101,102,103,201,202,203);

   EMPNO ENAME
________ _____________
       1 WANOZRAMAP
       2 GMREPEQFIN
       3 SKWBNXLCNF
     101 GVXUEOOQJM
     102 XGLASIZISR
     103 UVODELRDCI
     201 ZZZ
     202 ZZZ
     203 ZZZ

9 rows selected.

SQL> select empno,ename from mf_emp_union where empno=997;

   EMPNO ENAME
________ ________
     997 KING

SQL>

(2)c.EMPをalter table moveし、高速リフレッシュ


 ソースPDB(k3)のc.EMPをalter table moveし、ROWIDを全て更新する。合わせて索引もリビルドする。これは典型的な表の断片化解消のシナリオである。
SQL> conn c/c@k3
Connected.
SQL> select empno,ename,rowid from emp where empno in (1,2,3,101,102,103,201,202,203);

   EMPNO ENAME    ROWID
________ ________ _____________________
     201 ZZZ      AAASCEAASAAAFbtAAA
     202 ZZZ      AAASCEAASAAAFbtAAB
     203 ZZZ      AAASCEAASAAAFbtAAC

SQL> alter table emp move;
select empno,ename,rowid from emp where empno in (1,2,3,101,102,103,201,202,203);

Table EMP altered.

SQL> select empno,ename,rowid from emp where empno in (1,2,3,101,102,103,201,202,203);

   EMPNO ENAME    ROWID
________ ________ _____________________
     201 ZZZ      AAASCiAASAAAFbzAAB
     202 ZZZ      AAASCiAASAAAFbzAAC
     203 ZZZ      AAASCiAASAAAFbzAAD

select index_name,status from user_indexes where index_name like '%EMP%';
SQL> select index_name,status from user_indexes where index_name like '%EMP%';

INDEX_NAME              STATUS
_______________________ ___________
SYS_C_SNAP$_23PK_EMP    VALID
I_MLOG$_EMP             VALID
IDX1_EMP                UNUSABLE
PK_EMP                  UNUSABLE

alter index pk_emp rebuild;
SQL> alter index pk_emp rebuild;

Index PK_EMP altered.

SQL> alter index idx1_emp rebuild;

Index IDX1_EMP altered.

SQL> select index_name,status from user_indexes where index_name like '%EMP%';

INDEX_NAME              STATUS
_______________________ _________
SYS_C_SNAP$_23PK_EMP    VALID
PK_EMP                  VALID
IDX1_EMP                VALID
I_MLOG$_EMP             VALID

 ターゲットPDB(k5)にて、高速リフレッシュを実行する。高速リフレッシュはORA-12034エラーとなる。完全リフレッシュにより、正しい同期状態にすることができていることがわかる。
SQL> conn f/f@k5
Connected.
SQL> select empno,ename,rowid from mf_emp_union where empno in (1,2,3,101,102,103,201,202,203);

   EMPNO ENAME         ROWID
________ _____________ _____________________
       1 WANOZRAMAP    AAASBTAAWAAAAD7AAA
       2 GMREPEQFIN    AAASBTAAWAAAAD7AAB
       3 SKWBNXLCNF    AAASBTAAWAAAAD7AAC
     101 GVXUEOOQJM    AAASBTAAWAAAAD7ABk
     102 XGLASIZISR    AAASBTAAWAAAAD7ABl
     103 UVODELRDCI    AAASBTAAWAAAAD7ABm
     201 ZZZ           AAASBTAAWAAAAD9ACA
     202 ZZZ           AAASBTAAWAAAAD9ABk
     203 ZZZ           AAASBTAAWAAAAD9AC4

9 rows selected.

SQL> EXECUTE DBMS_MVIEW.REFRESH('mf_emp_union', 'f');  --★高速リフレッシュ

Error starting at line : 1 in command -
BEGIN DBMS_MVIEW.REFRESH('mf_emp_union', 'f'); END;
Error report -
ORA-12034: materialized view log on "C"."EMP" younger than last refresh
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 3020
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 2432
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 88
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 253
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 2413
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 2976
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 3263
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 3295
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 16
ORA-06512: at line 1
12034. 0000 -  "materialized view log on \"%s\".\"%s\" younger than last refresh"
*Cause:    The materialized view log was younger than the last refresh.
*Action:   A complete refresh is required before the next fast refresh.
SQL> EXECUTE DBMS_MVIEW.REFRESH('mf_emp_union', 'c');  --★完全リフレッシュ

PL/SQL procedure successfully completed.

SQL> select empno,ename,rowid from mf_emp_union where empno in (1,2,3,101,102,103,201,202,203);

   EMPNO ENAME         ROWID
________ _____________ _____________________
       1 WANOZRAMAP    AAASBTAAWAAAAD8ABo
       2 GMREPEQFIN    AAASBTAAWAAAAD8ABp
       3 SKWBNXLCNF    AAASBTAAWAAAAD8ABq
     101 GVXUEOOQJM    AAASBTAAWAAAAD8ABm
     102 XGLASIZISR    AAASBTAAWAAAAD8ABn
     103 UVODELRDCI    AAASBTAAWAAAAD9AAA
     201 ZZZ           AAASBTAAWAAAAD7ABr
     202 ZZZ           AAASBTAAWAAAAD7ABs
     203 ZZZ           AAASBTAAWAAAAD7ABt

9 rows selected.

(3)c.EMPをトランケートし、高速リフレッシュ


 ソースPDB(k3)のc.EMPをトランケートで全件削除する。
SQL> conn c/c@k3
Connected.
SQL> truncate table emp;

Table EMP truncated.

 ターゲットPDB(k5)にて、高速リフレッシュを実行する。高速リフレッシュはORA-12034エラーとなる。完全リフレッシュにより、正しい同期状態にすることができていることがわかる。
SQL> conn f/f@k5
Connected.
SQL> select empno,ename from mf_emp_union where empno in (1,2,3,101,102,103,201,202,203);

   EMPNO ENAME

       1 WANOZRAMAP
       2 GMREPEQFIN
       3 SKWBNXLCNF
     101 GVXUEOOQJM
     102 XGLASIZISR
     103 UVODELRDCI
     201 ZZZ
     202 ZZZ
     203 ZZZ

9 rows selected.

SQL> EXECUTE DBMS_MVIEW.REFRESH('mf_emp_union', 'f');  --★高速リフレッシュ

Error starting at line : 1 in command -
BEGIN DBMS_MVIEW.REFRESH('mf_emp_union', 'f'); END;
Error report -
ORA-12034: materialized view log on "C"."EMP" younger than last refresh
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 3020
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 2432
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 88
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 253
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 2413
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 2976
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 3263
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 3295
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 16
ORA-06512: at line 1
12034. 0000 -  "materialized view log on \"%s\".\"%s\" younger than last refresh"
*Cause:    The materialized view log was younger than the last refresh.
*Action:   A complete refresh is required before the next fast refresh.
SQL> EXECUTE DBMS_MVIEW.REFRESH('mf_emp_union', 'c');  --★完全リフレッシュ

PL/SQL procedure successfully completed.

SQL> select empno,ename from mf_emp_union where empno in (1,2,3,101,102,103,201,202,203);

   EMPNO ENAME
________ _____________
       1 WANOZRAMAP
       2 GMREPEQFIN
       3 SKWBNXLCNF
     101 GVXUEOOQJM
     102 XGLASIZISR
     103 UVODELRDCI

6 rows selected.

4.まとめ


 今回の調査、検証を踏まえ、明らかになったことはは以下の通り。
  • UNION ALLで複数表をまとめたMVIEWを作成することは可能
  • 高速リフレッシュを使うには、MLOGにROWIDを含め、かつ表の定義にROWIDおよびマーカーを追加する必要がある
  • ソース表でROWIDを変更する操作(例えば、ソース表の断片化解消のためのMOVEやインポートなど)をすると、高速リフレッシュはエラーとなる(完全リフレッシュが必要)
  • トランケートをすると、高速リフレッシュはエラーとなる(完全リフレッシュが必要)

 MLOGおよびMVIEWにROWIDを含める必要があるという制約は、UNION ALLを使うMVIEWではソースの行をPKだけでは特定できないからと思われる(複数のソース表の主キーの重複が想定されるため)。
 なお、今回検証結果は示していないが、MVIEW側でPKを定義すると、重複データが発生した場合にMVIEWのリフレッシュが一意制約違反で失敗するようにすることもできる。復旧のためには、重複データを特定しソース側で削除した後、完全リフレッシュが必要であることは言うまでもない。

参考


[1]Oracle Database データ・ウェアハウス・ガイド 19c

以上

コメント(0) 

Oracle 23c freeのオプティマイザ関連パラメータを調べる [オプティマイザ]

1.はじめに


 4/5未明のOracle ACE向けアナウンスで、オラクル社のGerald Venzl氏からOracle Database 23c Freeがリリースされたとの説明があった(参考[1])。これは開発者向けの無償版で、従来Xeと呼ばれていたものに相当するそうだ。正式な23cは現在ベータテスト中である中、開発者向けを無償で先にリリースするのは、23cのDeveloper firstの姿勢の本気度を感じさせられる。RACやDataGuardのような機能は使えないが、JSON等の新機能を試したりすることができるのは開発者に取って朗報だろう。正式なサポートはないが、Oracle Forumにスレッドがあるので活用するとよいだろう(参考[2])。
 23cのリリースでまず一番私が確認したかったのは、オプティマイザに影響を与えるパラメータである。デフォルト値が変更されたものや、新機能として追加されたものを把握することは、いずれ必要となる19cからの移行作業で必ず必要となるためである。本稿では、23cのオプティマイザ関連のパラメータについて、その調査方法と結果ついて共有したい。
 なお、Oracle Database 23c Freeの導入方法については、すでに日本語で紹介したブログもあるので、ここで特筆する必要はないだろう。ちなみに、私はVirtual Box VMのイメージを使ったが、特段難しいことはなく利用することができた。

2.オプティマイザのパラメータ確認方法


 オプティマイザに影響を与えるパラメータの確認方法はいくつかあるが、私が個人的に最も信頼しているのは10053トレースである。10053トレースの取得方法は以下の通り。今回の場合SQLはなんでも良いので、select 1 from dualとした。
-- to enable the 10053 trace
alter session set events '10053 trace name context forever';
  execute any SQL
-- stop tracing
alter session set events '10053 trace name context off';

 結果は以下のようにtraceディレクトリ配下にSID_ora_PID.trcという名前で出力される。
[oracle@localhost trace]$ ls -ltr /opt/oracle/diag/rdbms/free/FREE/trace/ | tail
-rw-r-----. 1 oracle oinstall   7077 Apr  5 20:23 FREE_dbrm_1924.trm
-rw-r-----. 1 oracle oinstall  37378 Apr  5 20:23 FREE_dbrm_1924.trc
-rw-r-----. 1 oracle oinstall  68439 Apr  5 20:23 FREE_ora_12524.trm
-rw-r-----. 1 oracle oinstall 126447 Apr  5 20:23 FREE_ora_12524.trc ★
-rw-r-----. 1 oracle oinstall   1731 Apr  5 20:27 FREE_gcr2_12649.trm

 トレースファイルの中を確認すると、以下のようにPARAMETERS USED BY THE OPTIMIZERというセクションがあり、そこにオプティマイザに影響を与える(隠し)初期化パラメータが出力される。PARAMETERS WITH ALTERED VALUESはデフォルト値から変更されたパラメータ、PARAMETERS WITH DEFAULT VALUESはデフォルト値から変更のないパラメータを表す。
Trace file /opt/oracle/diag/rdbms/free/FREE/trace/FREE_ora_12524.trc
Oracle Database 23c Free, Release 23.0.0.0.0 - Developer-Release
Version 23.2.0.0.0
...
***************************************
PARAMETERS USED BY THE OPTIMIZER
********************************
  *************************************
  PARAMETERS WITH ALTERED VALUES
  ******************************
Compilation Environment Dump
_swat_ver_mv_knob                   = 0
Bug Fix Control Environment


  *************************************
  PARAMETERS WITH DEFAULT VALUES
  ******************************
Compilation Environment Dump
optimizer_mode_hinted               = false
optimizer_features_hinted           = 0.0.0
parallel_execution_enabled          = false
parallel_query_forced_dop           = 0
parallel_dml_forced_dop             = 0
parallel_ddl_forced_degree          = 0
parallel_ddl_forced_instances       = 0
_query_rewrite_fudge                = 90
optimizer_features_enable           = 23.1.0

 多くの初期化パラメータは_(アンダースコア)が接頭辞となる隠しパラメータであり、マニュアルには記載されていない。このため、以下のSQLでそれぞれのパラメータの説明を取得する(x$ksppi.ksppdescに初期化パラメータの説明がある)。簡単な説明しかないものの、概ねどのような機能を持つのかくらいのことはわかるだろう。
set markup csv on
spool /tmp/initparam19c.csv
SELECT a.ksppinm "Parameter", b.KSPPSTDF "Default Value", a.KSPPDESC "DESCRIPTION",
       b.ksppstvl "Session Value", 
       c.ksppstvl "Instance Value",
       decode(bitand(a.ksppiflg/256,1),1,'TRUE','FALSE') IS_SESSION_MODIFIABLE,
       decode(bitand(a.ksppiflg/65536,3),1,'IMMEDIATE',2,'DEFERRED',3,'IMMEDIATE','FALSE') IS_SYSTEM_MODIFIABLE
FROM   x$ksppi a,
       x$ksppcv b,
       x$ksppsv c
WHERE  a.indx = b.indx
AND    a.indx = c.indx
order by 1
/

3.取得結果


 上記の確認方法を使って、Oracle Database 23c Freeと、Oracle 19.11.0(EE)とで比較を行った。比較結果の詳細を確認したい場合は、参考[3]を参照されたい。ここでは主な変更点について記載しておきたい。
 まず全体のパラメータ数は、23cが658個に対して、19cは613個と45増えている。具体的には以下の通り、23cの新規パラメータは46個あり、19cにあって23cにないパラメータが1つ存在した。19cからの移行においては、新しいオプティマイザの機能追加が想定しない挙動(実行計画)となる可能性があるため、必要に応じて見直しする対象となるだろう(具体的には値がtrueとなっているものは、機能を無効とするためにfalseに変更するといった対処など)。

◇23cのオプティマイザ関連の新規パラメータ
# 23.2.0 value description
10 _ansi_join_mv_rewrite_enabled true enable/disable ansi join mv rewrite
17 _autoptn_costing false DBMS_AUTO_PARTITION is compiling query for cost estimates
40 _cell_index_scan_enabled true enable CELL processing of index FFS
41 _cell_iot_scan_enabled true enable CELL processing of IOT FFS
44 _cell_metadata_compression AUTO Cell metadata compression strategy
62 _cross_con_remove_pushed_preds false remove pushed predicates from query fetching across containers
82 _enable_columnar_cache 1 enable 12g bigfile tablespace
109 _groupby_orderby_combine 5000 groupby/orderby don't combine threshold
123 _inmemory_hpk4sql_flags 0 In-Memory HPK4SQL flags
129 _json_qryovergen_rewrite true enable/disable JSON query over generation function rewrite
160 _obsolete_result_cache_mode MANUAL USERS SHOULD NOT SET THIS! Used for old qksced parameterof result_cache_mode
232 _optimizer_exists_to_any_rewrite true consider exists-to-any rewrite of subqueries
286 _optimizer_nested_loop_join on favor/unfavor nested loop join
303 _optimizer_push_gby_into_union_all true consider pushing down group-by into union-all branches
323 _optimizer_subsume_vw_sq on consider subsumption of views or subqueries
341 _optimizer_use_stats_models false use optimizer statistics extrapolation models
353 _optimizer_wc_filter_pushdown true enable/disable with clause filter predicate pushdown
387 _px_adaptive_dist_nij_enabled on enable adaptive distribution methods for left non-inner joins
399 _px_extended_join_skew_handling true enables extended skew handling for parallel joins
424 _px_parallelize_non_native_datatype true enable parallelization for non-native datatypes
427 _px_partition_load_skew_handling on enable partition load skew handling
428 _px_partition_load_skew_threshold 3 partition loads bigger than threshold times average are skewed
446 _px_window_skew_handling true enable window function skew handling
447 _qa_lrg_type 0 Oracle internal parameter to specify QA lrg type
491 _rowsets_use_work_heap_buffer true allow/disallow use of work heap buffer for values for rowsets
497 _slave_mapping_skew_handling true enables skew handling for slave mapping plans
516 _sqlexec_hash_based_distagg_ser_civ_enabled true enable hash based distinct aggregation in serial/CIV queries
518 _sqlexec_hash_based_set_operation_enabled true enable/disable hash based set operation
519 _sqlexec_hash_rollup_enabled true enable hash rollup
523 _sqlexec_use_delayed_unpacking true enable/disable the usage of delayed unpacking
526 _sqlexec_window_function_settings 63 execution settings for window functions
531 _swat_ver_mv_knob 0 Knob to control MV/REWRITE behavior
542 _use_dirty_reads 0 enable the use of column statistics for DDP functions
553 _zonemap_refresh_within_load true Control the refresh of basic zonemaps during/after data load
574 escrow_dirty_cursor 0 whether to encrypt newly created tablespaces
575 escrow_internal_cursor 0 whether to encrypt newly created tablespaces
578 group_by_position_enabled false enable/disable group by position
579 gwr_trigger_enabled 0 enable/disable group by position
589 json_expression_check off enable/disable JSON query statement check
591 memoptimize_writes HINT write data to IGA without memoptimize_write hint
597 optimizer_cross_shard_resiliency false enables resilient execution of cross shard queries
614 optimizer_use_sql_quarantine true enable use of sql quarantine
644 shard_enable_raft_follower_read true enable read from follower replications units in a shard
645 shard_queries_restricted_by_key false add shard key predicates to the query
656 translate_table_name_hash 0 number of active transactions per rollback segment
658 valid_shard_session_key 0 User process dump directory


◇23cで廃止されたオプティマイザ関連の新規パラメータ
19.11.0 value description
_optimizer_quarantine_sql true enable use of sql quarantine


 次に、同じパラメータであるが値が異なるものを調べたところ、27個あった。この27のうち、19cで私が意図的に変更したものや、バージョンや環境に依存するもの(CPU数やメモリサイズ等)を除くと、以下の4つのパラメータが残った。これらデフォルト値が変わっているものもオプティマイザの挙動に影響を与えるため、移行時は留意する必要がある。

◇19cと23cでデフォルト値が変更されたオプティマイザ系パラメータ
# 23.2.0 value description
36 _cdb_special_old_xplan false display old-style plan for CDB special fixed table
275 _optimizer_key_vector_payload_dim_aggs true enables or disables dimension payloading of aggregates in VT
515 _sqlexec_hash_based_distagg_enabled true enable hash based distinct aggregation for gby queries
626 parallel_execution_enabled false policy used to compute the degree of parallelism (MANUAL/LIMITED/AUTO/ADAPTIVE)


4.おわりに


 本稿では23cのOracle Database Freeと、19.11.0(EE)のオプティマイザ関連パラメータを、10053トレースを取得し比較した。Developer EditionとEEではそもそも異なる設定もあるだろうし、そもそも23cのEE版はベータテスト中という状況であるので、この結果を直接どうこう議論できるものではないだろう。実際の移行においては、23cが正式にリリースされた後、同様の方法でオプティマイザの挙動に影響するパラメータを洗い出す必要があるだろう。それでも、23cと19cでどの程度の変更があるのかの感覚を掴むことはできたと思う。

以上

参考


[1]:Introducing Oracle Database 23c Free - Developer Release, Oracle Database Insider, Gerald Venzl
[2]:Oracle Database Free - Developer Release, Oracle Forum
[3]:オプティマイザ関連初期化パラメータの差分確認結果(23cと19c)(OptimizerParameter23vs19.xlsx)

コメント(0)