RAC One Node の検証 その4

<RAC One Node の検証 その4>
ペンネーム : ダーリン

さてさて、RAC One Node の検証も 4 回目を迎えました。RAC の
ようで、でもちょっと違う微妙な構成にも徐々になれてきたでしょ
うか。
なかなか環境が手元にないと簡単な検証を行うにも困ってしまいま
すね。RAC One Node をちょっと触ってみたいけど環境がなくて…
という読者の方は、このメルマガで少しでも雰囲気を味わっていた
だければ幸いです。

前回、Omotion 中の Oracle インスタンスのアラートログから以下
のメッセージを拾い上げました。”transactional” ということはも
しかすると Omotion の処理時間が延びてしまう可能性があるとい
うことでしょうか。
今週はこの “transactional” について少し見ていきます。

————————————————
Shutting down instance (transactional)
————————————————

これは、( Omotion 中に )「データベースインスタンスを transactional
モードで停止します。」という意味です。

Oracle ではデータベースインスタンスを停止する場合には以下の
オプションがあります。
・NORMAL
・IMMEDIATE
・TRANSACTIONAL
・ABORT

また、SHUTDOWN 時に TRANSACTIONAL オプションが指定された場合
の動作については、マニュアルに以下のような説明があります。

・文が発行された後は、新しい接続や新しいトランザクションの
  開始は許可されません。
・すべてのトランザクションが完了すると、まだインスタンスに
  接続されているすべてのクライアントが切断されます。
・この時点で、インスタンスはSHUTDOWN IMMEDIATE文を発行した
  場合と同じように停止します。
・次にデータベースを起動するときに、インスタンス・リカバリ
  手順は必要ありません。

つまり、全てのトランザクションが完了しないと SHUTDOWN 処理自
体が終了しないということになります。よって、TRANSACTION モー
ドを使って処理が行われている Omotion もこれに従わざるをえま
せん。

今回のシリーズ 2 回目で少しふれましたが Omotion は主にサーバ
のメンテナンスなどのシーンで使われるはずです。
ということは、、、、
– メンテナンス目的の計画停止の際に Omotion を発行して、
– インスタンスを移動し、
– 切り替えが終わったらサーバを停止して、、、、
– と思ったら、まだインスタンスが切り替わっていなぁ~い!!
ということになってしまうかもしれません。

ところで読者のみなさんの環境ではサーバメンテナンスでインスタ
ンスを停止する場合は、どのようにしているでしょうか。
いくらトランザクション中だと言っても、いつまでもそれが終了す
るまで待機することはないですよね?
通常は、IMMEDIATE モードでSHUTDOWN させ、実行中のトランザク
ション処理についてもロールバックさせるなどの対応をされている
のではないでしょうか。

Omotion といえどもやはりいつまでもトランザクションの終了を待
ちたくはありません。で、どうするかというと、、、

Omotion 実行時の入力項目を今一度確認するとこんな設定項目があ
ります。

———————————————————–
Specify maximum time in minutes for migration to complete
(max 30) [30]: 2 <<<< (2)
———————————————————–

これは、「移行終了までの最大時間 [ 分 ](最大 30)」という
ことで、どうやら上限を設定することができるようです。
デフォルトが 30 分とのことですが、ちょっと我慢強くないので
2 分で再度確認してみます。

また、前回のテストスクリプトではインサートごとにコミットし
ているのでトランザクションの時間は非常に短かいため、設定値
2 分に対しては影響がありません。よって、今回はコミットまで
の時間がちょっと長くなるように改修 ( 下記「テストスクリプト
改修版」参照 ) して検証してみます。

改修ポイントは COMMIT の間隔を設定するようにしたところです。
検証では 4 分 ( 240 秒 ) に設定しています。
これで、「移行終了までの最大時間」までにトランザクションが
終了しなかった場合にどうなるのかを確認できます。

では今回もテストスクリプト改修版を実行しながら Omotion !!

$ Omotion

(今回は oel55sv02 側 から oel55sv01 側への Omotion です。 )

まず、Omotion の標準出力に以下のようなメッセージが表示されました。

-----------------------------------------------------------
RAC One Node databases on this cluster:

    

Omotion Started...
Starting target instance on oel55sv01...
Migrating sessions...
Stopping source instance on oel55sv02...
Timeout exceeded, aborting instance...  <<< select idate
  2       , cnt
  3       , csid
  4       , to_char(trunc(dtime/60),'FM999') || ':'
  5         || to_char(mod(dtime,60),'FM00') dtime
  6    from ora3_test order by idate

IDATE                 CNT CSID       DTIME
------------------- ----- ----- ----------
2010/08/03 00:04:55     1 RON_2       0:04
2010/08/03 00:05:00     2 RON_2       0:09
2010/08/03 00:05:05     3 RON_2       0:14
2010/08/03 00:05:10     4 RON_2       0:19
        :                  :            :
        :                  :            :
2010/08/03 00:07:50    36 RON_2       2:59
2010/08/03 00:07:55    37 RON_2       3:04
2010/08/03 00:08:00    38 RON_2       3:09
2010/08/03 00:11:25     1 RON_1       6:34 <<< データ欠損!?
2010/08/03 00:11:30     2 RON_1       6:39
2010/08/03 00:11:35     3 RON_1       6:44
2010/08/03 00:11:40     4 RON_1       6:49
2010/08/03 00:11:45     5 RON_1       6:54
2010/08/03 00:11:50     6 RON_1       6:59
        :                  :            :
        :                  :            :

-----------------------------------------------------------

 
 IDATE   INSERT 時刻
 CNT     接続した状態での INSERT の累計回数。再接続でクリア
 CSID    接続先の SID
 DTIME   スクリプト開始後からの経過時間

上記の 00:11:25 の接続先 SID が変わったタイミングでデータが
欠損してしまいました。

アラートログを確認して時系列と挙動を確認してみましょう。

まずは、移行元のインスタンス( oel55sv02 側)です。

-----------------------------------------------------------
       

Tue Aug 03 00:08:52 2010
Shutting down instance (transactional)
Stopping background process SMCO
Shutting down instance: further logons disabled
Tue Aug 03 00:08:57 2010
Setting Resource Manager plan DEFAULT_MAINTENANCE_PLAN via parameter
Stopping background process QMNC
Tue Aug 03 00:08:57 2010
Stopping background process CJQ0
Stopping background process MMNL
Stopping background process MMON
Tue Aug 03 00:10:54 2010
License high water mark = 7
USER (ospid: 708): terminating the instance
Instance terminated by USER, pid = 708

-----------------------------------------------------------

00:08:52 に TRANSACTIONAL モードでインスタンスの停止が始まっ
ています。
で、00:10:54 にいきなり停止?(terminating the instance)
確かに、Omotion で指定した待機時間 ( 2 分 ) とほぼ同じ時間
待機している様子がみえます。

では、移行先のインスタンス ( oel55sv01 側 ) の方も確認して
おきましょう。

-----------------------------------------------------------
       

Tue Aug 03 00:10:58 2010
Reconfiguration started (old inc 140, new inc 142)
List of instances:
 1 (myinst: 1)
 Global Resource Directory frozen
 * dead instance detected - domain 0 invalid = TRUE
 Communication channels reestablished

       

Tue Aug 03 00:10:59 2010
Instance recovery: looking for dead threads
Reconfiguration complete
Beginning instance recovery of 1 threads
Started redo scan
Completed redo scan
 read 25 KB redo, 26 data blocks need recovery
Started redo application at
 Thread 2: logseq 7, block 15237
Recovery of Online Redo Log: Thread 2 Group 4 Seq 7 Reading mem 0
  Mem# 0: +DATA/ron/onlinelog/group_4.270.723224611
  Mem# 1: +DATA/ron/onlinelog/group_4.271.723224633
Completed redo application of 0.01MB
Tue Aug 03 00:11:10 2010
Completed instance recovery at
 Thread 2: logseq 7, block 15287, scn 4924815
 26 data blocks read, 26 data blocks written, 25 redo k-bytes read
Thread 2 advanced to log sequence 8 (thread recovery)

-----------------------------------------------------------

ほぼ同じタイミングで 00:10:58 から Reconfigration が始まって
います。
通常の RAC 構成のノードが停止した時と同じようにマスタノード
の再設定などが行われているようです。

おっと、途中でこんなメッセージが。
———————————————————–
Beginning instance recovery of 1 threads
———————————————————–
インスタンスリカバリ…..

TRANSACTIONAL では、インスタンスリカバリは不要なはずです。
SHUTDOWN の他のモードも含めてよくよく見てみると、インスタン
スリカバリが必要になるのは、やはり、SHUTDOWN ABORT….

どうやら、Omotion の待機時間を超えてトランザクションが終了し
ない場合は ABORT 相当の処理が実行されるようですねぇ。移行元
のインスタンスがいきなり停止しているように見えた理由も納得が
いきます。

ちなみに、テストスクリプト内では 5 秒ごとにデータを INSERT
して、4 分ごとに COMMIT を発行するようにしているので、移行
元のインスタンスが停止する直前の 00:10:50 までは INSERT さ
れていたはずです。
ここで 移行元のインスタンス ( oel55sv02 側 ) で ABORT 相当の
処理が実施されたため移行先のインスタンス ( oel55sv01 側 ) で
インスタンスリカバリが実行され、直前の COMMIT タイミング時点
まで ( 00:08:00 時点 ) ロールバックされたと考えられます。

・Omotion ではトランザクションモードで移行元のインスタンスを
  停止している。
・トランザクションモードでインスタンスを停止する場合は、実行
  中のトランザクションが終了するまで停止処理は待機する。
・アプリケーションからのトランザクションが継続していると
  Omotion は制限時間まで待機する。(デフォルトは 30 分)
  制限時間に達すると、ABORT 相当の処理で移行元のインスタンス
  は停止する。
・ABORT 相当の処理が行われると、実行中のトランザクションはロー
  ルバックされ、該当処理のデータは更新されない。

よって、運用上 Omotion を実行する場合は実際のトランザクション
にかかる時間を十分に把握したうえで Omotion の待機時間を設定す
る必要があります。(そうしないと、途中まで進行した処理がロー
ルバックされてしまう可能性があります。)
あるいは、計画メンテナンスなどの作業が控えている状況において
は、延々とトランザクションの終了を待ち続けるわけにもいかない
でしょうから、事前に全ての処理を停止しておいてもらう様に周知
しておく方が望ましいでしょう。
このあたりは通常の運用と同じ考慮が必要ということです。

次回は、Omotion は使わずにガッツリとインスタンスを落としてみ
ます。つまり障害時のシミュレートです。
どんな挙動を示すのでしょうか

==

補足1「テストスクリプト改修版」

-------------------------------
#/bin/sh

CNT=0

#
sqlplus ora3/ora3@ron &lt;&lt;_EOF_
truncate table ora3_test2;
truncate table ora3_start;
insert into ora3_start (sdate) values (sysdate);
commit;
exit
_EOF_

#
while [ ${CNT} -lt 2 ];
do
sqlplus ora3/ora3@ron <<_EOF_


DECLARE
  v_start_date       date        := NULL;
  v_sysdate          date        := NULL;
  v_time_min         number      := 0;
  v_time_sec         number      := 0;
  v_insert_interval  number      := 5;
  v_commit_interval  number      := 240;
  v_sleep            number      := 5;
  v_count            number      := 0;
  v_instance_name    varchar2(5) := NULL;

BEGIN
  select sdate into v_start_date from ora3_start;
  v_sysdate := sysdate;
  v_time_min := to_number(to_char(v_sysdate,'mi'));
  v_time_sec := to_number(to_char(v_sysdate,'ss'));
  v_sleep    := v_insert_interval - mod(v_time_min*60+v_time_sec,v_insert_interval);
  DBMS_LOCK.SLEEP(v_sleep);

  LOOP

    v_sysdate := sysdate;
    v_time_min := to_number(to_char(v_sysdate,'mi'));
    v_time_sec := to_number(to_char(v_sysdate,'ss'));
    v_count := v_count + 1;
    insert into ora3_test (idate,cnt,csid,dtime) values (v_sysdate,v_count,sys_context('userenv','instance_name'),(v_sysdate - v_start_date)*60*60
*24);

    IF (mod(v_time_min*60+v_time_sec,v_commit_interval) < v_insert_interval) THEN
      COMMIT;
    END IF;

    v_sysdate := sysdate;
    v_time_min := to_number(to_char(v_sysdate,'mi&'));
    v_time_sec := to_number(to_char(v_sysdate,'ss'));
    v_sleep    := v_insert_interval - mod(v_time_min*60+v_time_sec,v_insert_interval);
    DBMS_LOCK.SLEEP(v_sleep);

  END LOOP;
END;
/
exit
_EOF_

echo "Exit at:" `date '+%Y/%m%d %H%M%S'`
CNT=`expr ${CNT} + 1`

sleep 1
done

exit

-------------------------------

補足2「テストテーブル」

-------------------------------
create table ora3_start (sdate date);
create table ora3_test (idate date,cnt number,csid char(10),dtime number);
-------------------------------