もう2020年になりましたが、去年の暮、19c新機能の検証をしていたので、紹介していきます。
まずはActive Data Guard DMLリダイレクトの検証で、検証に使用した環境は以下の通りです。
Active Data Guard DMLリダイレクトの概要は以下の通りです。
スタンバイ・データベースで発行したDMLはプライマリ・データベースにリダイレクトされて実行される。
プライマリ・データベースで実行されたDMLがスタンバイ・データベースに伝搬されると、スタンバイ・データベースのセッションから更新された内容が見えるようになる。
高頻度のDMLは想定していない。
スタンバイ側でDMLの発行は出来るけれど、実際に実行されるのはあくまでプライマリ側だというのがポイントですね。
さもないと、更新可能スナップショット*1のようにコンフリクトの解消が必要になってきます。
以下、検証です。
まずはActive Data Guardを構築します。構成は以下の通りです。
DGMGRL> show configuration;
Configuration - orcl_active_dg
Protection Mode: MaxPerformance
Members:
orcl - Primary database
orcldg - Physical standby database
Fast-Start Failover: Disabled
Configuration Status:
SUCCESS (status updated 64 seconds ago)
スタンバイ側からinsertを実行してみます。
SQL> select count(*) from t1;
COUNT(*)
----------
142523903
SQL> insert into t1(col1) values(1);
insert into t1(col1) values(1)
*
ERROR at line 1:
ORA-16000: database or pluggable database open for read-only access
ADG_REDIRECT_DMLが有効でないと上記の通りエラーになるので、システムまたはセッション単位で有効にします。
SQL> ALTER SESSION ENABLE ADG_REDIRECT_DML;
Session altered.
SQL> insert into t1(col1) values(1);
1 row created.
SQL> select count(*) from t1;
COUNT(*)
----------
142523904
commitする前に結果を確認できていますね。
当然、ロールバックすれば更新前の状態が参照できます。
ちなみに、普通の初期化パラメータと同じ構文で設定しようとするとエラーになります。
SQL> alter session set adg_redirect_dml=true;
alter session set adg_redirect_dml=true
*
ERROR at line 1:
ORA-02096: specified initialization parameter is not modifiable with this
option
「高頻度のDMLは想定していない」との事なので、やったらどうなるのか検証します。
プライマリ側
SQL> begin
2 for i in 1..100 loop
3 insert into t1(col1) values(i);
4 end loop;
5 end;
6 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.07
スタンバイ側
SQL> begin
2 for i in 1..100 loop
3 insert into t1(col1) values(i);
4 end loop;
5 end;
6 /
PL/SQL procedure successfully completed.
Elapsed: 00:01:33.47
プライマリで 0.07秒の処理が、1分半もかかります。
どこで時間がかかっているのか確認する為、SQLトレースを取得してみました。
call count cpu elapsed disk query Current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 2 0.00 0.00 0 0 0 0
Execute 2 0.01 93.35 0 0 0 1
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.02 93.35 0 0 0 1
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
Disk file operations I/O 48 0.00 0.00
single-task message 1 0.01 0.01
SQL*Net message from dblink 210 0.01 0.09
SQL*Net message to dblink 209 0.00 0.00
SQL*Net vector data to dblink 101 0.00 0.00
standby query scn advance 100 1.05 93.30
********************************************************************************
処理時間の殆どがstandby query scn advanceですね。
プライマリでのデータ更新が適用されてからスタンバイ側のクエリSCNが更新されるので、スタンバイでクエリを実行するとstandby query scn advance待機が発生するという訳です。
尚、この環境では同一サーバ上にプライマリ・スタンバイ双方のDBが存在するのでプライマリースタンバイ間の通信にかかる時間はわずかで、リアルタイム適用が有効となっているのでプライマリ側の処理はすぐにスタンバイ側に反映されます。
逆の場合は上記のstandby query scn advance待機が発生する分、余計に時間がかかってしまうようです。
次にロック競合が発生するDMLを実行してみました。
プライマリ側
SQL> delete from t1 where col1=2;
6 rows deleted.
Elapsed: 00:00:37.57
スタンバイ側
SQL> delete from t1 where col1=2;
ERROR at line 1:
ORA-02049: timeout: distributed transaction waiting for lock
ORA-02063: preceding line from ADGREDIRECT
ロックが獲得できず、エラーになってしまいました。
そこでスタンバイ側で発行したupdateで、プライマリ側でロックが取得されるのを確認してから、プライマリで実行してみました。
スタンバイ側
SQL> delete from t1 where col1=2;
6 rows deleted.
Elapsed: 00:00:47.36
プライマリ側
SQL> delete from t1 where col1=2;
6 rows deleted.
Elapsed: 00:01:05.33
スタンバイ側の遅い処理が終わるまで、ずっと待たされてしまいます。まあ、ロック競合しているのだから当然です。
プライマリ側で先にロック獲得した場合は、スタンバイ側は待機せずにエラーになるようです。
insertならば競合しないだろうという事で、insert select でテストしてみます。
プライマリ側
スタンバイ側
プライマリがで1秒もかからない処理で、スタンバイでは11分以上もかかってしまいました。
これはstandby query scn advanceでは説明付かなそうです。
一体、何に11分以上もかかっているのか・・・?
Active Data Guard DMLリダイレクトの検証(2)に続きます。