しばちょう先生の試して納得!DBAへの道

しばちょう先生の試して納得!DBAへの道 indexページ▶▶

しばちょう先生による技術解説セミナー。
動画、資料を公開中です。

>> 最新のセミナーをチェック

しばちょう先生の試して納得!DBAへの道
第33回 ASMのリバランスの動作

みなさん、こんにちは。涼しくて過ごし易くなってきましたね。食欲の秋とは良く言ったもので、毎年体重が増加する季節なので今年は少し気を付けたいと思っている、"しばちょう"こと柴田長(しばた つかさ)です。

前回の連載の冒頭でご紹介させて頂いたJapan Oracle User Group (JPOUG) 主催の大規模イベントJPOUG> SET EVENTS 20140907 が2014年9月7日(日) に開催されました。雨の中にも関わらず多くの方々にご参加頂きまして、誠にありがとうございました!

さて、今回の連載は前回中断させて頂いたASM編へ戻りたいと思います。第31回のI/O性能の向上において既にASMのリバランスを体験して頂いておりますが、ほとんど説明出来ていませんでしたので今回はリバランスの動作にフォーカスさせて頂きます。ところで、リバランスがなかなか終わらない。という経験をお持ちの方はいらっしゃいますでしょうか?今、どのぐらいの進捗なのか?残り時間は?と不安を覚えた方もいらっしゃるかもしれませんね。そのような不安を解消する為には、リバランスが具体的にどのような順番でどのような処理を実行しているのかを把握し、かつ進捗状況を確認するスキルを身につけることが大切だと思いますので、是非とも今回の演習を通して体験してみてくださいね。そんなこと知っているよ。という方へのメッセージとしては、リバランスはRebalanceフェーズとCompactionフェーズの2つのフェーズで構成されていることを目で見てみたいと思いませんか?とだけ投げかけておきますね。興味が沸いてきましたかね? さあ、今回も張り切って体験しちゃいましょう!

以下の演習をOracle Database 11g Release 2 (11.2.0.4)のデータベースで試してみてください。


1. 3本のASM ディスクで構成される高冗長性のASMディスク・グループDG_HIGHを作成してください。

[grid@vm11204]$ sqlplus / as sysasm
SQL>

-- どのASMディスク・グループにも属していないASMディスクの検出
set linesize 150 pages 500
col NAME for a12
col HEADER_STATUS for a14
col PATH for a20
select GROUP_NUMBER, DISK_NUMBER, NAME, HEADER_STATUS, PATH
  from V$ASM_DISK
 where GROUP_NUMBER = 0
 order by PATH ;

GROUP_NUMBER DISK_NUMBER NAME         HEADER_STATUS  PATH
------------ ----------- ------------ -------------- --------------------
           0           1              FORMER         /dev/sdj1
           0          11              FORMER         /dev/sdk1
           0           7              FORMER         /dev/sdl1
           0           8              FORMER         /dev/sdm1


-- 3本のASM Diskで構成される高冗長性のASMディスク・グループDG_HIGHの作成
create diskgroup DG_HIGH
  high redundancy
    regular failgroup FG1 disk '/dev/sdj1'
    regular failgroup FG2 disk '/dev/sdk1'
    regular failgroup FG3 disk '/dev/sdl1'
  attribute
    'COMPATIBLE.ASM'   = '11.2.0.4',
    'COMPATIBLE.RDBMS' = '11.2' ;

はい、こちらの演習は「第30回 ASMディスク・グループの作成と使用量の確認」の復習となりますので、恐らく問題無く実行できたかと思います。ただし、ここでは二点だけ補足させて頂きます。

一点目は、V$ASM_DISK.HEADER_STATUSの値についてです。上記の私の回答例では「FORMER」となっていますが、これはどのような状態でしょうか?どのマニュアルに載っているのか?という点です。そのような場合は、対象のビューの解説を探してみるのが一番なので、リファレンス・マニュアルをまずは確認してみることをお勧めします。V$ASM_DISKビューのHEADER_STATUSの説明箇所には、全部で8個のステータスの種類と意味が記述されていましたよね。ちなみに「FORMER」の説明では「ディスクは以前はディスク・グループのメンバーであったが、グループから完全に削除されている。これは、ALTER DISKGROUP文を使用して新しいディスク・グループに追加できる。」とあります。ALTER DISKGROUP文でしか追加できないの?と思ってしまいそうな説明ですが、そんなことはありません。CREATE DISKGROUP文にも含めることができますのでご安心くださいね。

二点目は、ASMディスク・グループを作成する際のCREATE DISKGROUP文で指定している、COMPATIBLE.ASMディスク・グループ属性についてです。Oracle Database 11gのOracle ASMでは、CREATE DISKGROUP文、ASMCMDユーティリティの mkdgコマンド、およびOracle Enterprise Managerの「ディスク・グループの作成」ページを使用する場合は、10.1がCOMPATIBLE.ASM属性のデフォルト設定になりますが、ASMCAを使用してディスク・グループを作成する場合は、11.2がデフォルト設定になります。ASMディスク・グループを作る方法によって、デフォルト値が異なるので、毎回指定するクセを付けておいた方が良いかもですね。

さて、この属性値はOracle ASMインスタンスが稼働しているソフトウェア・バージョン以下である必要があります。と言っても、以下であればどのような値でも構わないかと言えば、それは間違いです。なぜならば、他の2つのディスク・グループ属性「COMPATIBLE.RDBMS」、「COMPATIBLE.ADVM」の設定値との組み合わせにより、使用可能になるASMの機能が定義されているからです。それは何処に記述されているのか?答えは、Automatic Storage Management管理者ガイドの「ディスク・グループの互換性属性設定により使用可能になる機能」を確認してみてください。私の回答例において、'COMPATIBLE.ASM'='11.2.0.4' を設定している理由は「最大値が1024のASM_POWER_LIMIT」機能を利用したいからです。マニュアルに従えば11.2.0.2でも使用できますけどね。ここで気付いて頂きたいのは、ASMの新機能が大きなリリース(Release 1、Release 2)の単位だけではなく、より小さなリリースの際にも追加されているという点ですね。

この演習1で意図した通りにASMディスク・グループが作成されているかの確認もしっかり実施しておきましょうね。。万が一のトラブル時に、「このように作ったつもりです。」とだけ口頭で報告されても100%は信用出来ませんからね。必ず証拠を残しておくクセも付けておきましょう。

[grid@vm11204]$ sqlplus / as sysasm
SQL>
-- 作成したASMディスク・グループDG_HIGHの確認
set lines 110 pages 500
col NAME for a10
col STATE for a10
col TYPE for a8
col COMPATIBILITY for a15
col DATABASE_COMPATIBILITY for a15
select * from V$ASM_DISKGROUP where NAME = 'DG_HIGH' ;

GROUP_NUMBER NAME    SECTOR_SIZE BLOCK_SIZE ALLOCATION_UNI STATE   TYPE TOTAL_MB FREE_MB
------------ ------- ----------- ---------- -------------- ------- ---- -------- -------
           3 DG_HIGH         512       4096        1048576 MOUNTED HIGH     3057    2898

HOT_USED_MB COLD_USED_MB REQUIRED_MIRROR_ USABLE_FILE_MB OFFLINE COMPATIBILITY DATABASE_COMPAT
----------- ------------ ---------------- -------------- ------- ------------- ---------------
          0          159                0            966       0 11.2.0.4.0    11.2.0.0.0


-- ASMディスク・グループDG_HIGH(GROUP_NUMBER=3)のASMディスクの確認
col NAME for a12
col HEADER_STATUS for a8
col PATH for a12
col FAILGROUP for a12
select GROUP_NUMBER, DISK_NUMBER, HEADER_STATUS, PATH, NAME, FAILGROUP, TOTAL_MB, FREE_MB
  from V$ASM_DISK
 where GROUP_NUMBER = 3
 order by 2 ;

GROUP_NUMBER DISK_NUMBER HEADER_S PATH       NAME         FAILGROUP TOTAL_MB FREE_MB
------------ ----------- -------- ---------- ------------ --------- -------- -------
           3           0 MEMBER   /dev/sdj1  DG_HIGH_0000 FG1           1019     966
           3           1 MEMBER   /dev/sdk1  DG_HIGH_0001 FG2           1019     966
           3           2 MEMBER   /dev/sdl1  DG_HIGH_0002 FG3           1019     966


2. ASMディスク・グループDG_HIGH上に配置される900MBの表領域TBS33を作成し、その表領域をデフォルト表領域とするTRYユーザー上に800MBの表TAB33を作成して下さい。

[oracle@vm11204]$ sqlplus / as sysdba
SQL>
-- 表領域TBS33の作成とTRYユーザーの作成
create tablespace TBS33 datafile '+DG_HIGH(DATAFILE)' size 900m ;
create user TRY identified by TRY default tablespace TBS33 ;
grant CONNECT, RESOURCE to TRY ;

-- 800MBの表TAB33を作成
connect TRY/TRY
create table TAB33 (COL1 number, COL2 char(1000), COL3 char(1000)) tablespace TBS33 ;
create sequence SEQ33 start with 10000001 increment by 1;
insert /*+append */ into TAB33
  select SEQ33.nextval, 'a', 'b'
    from (select 0 from all_catalog where rownum <= 800),
         (select 0 from all_catalog where rownum <= 3*128);
commit ;

-- 表TAB33のサイズ確認
col SEGMENT_NAME for a16
select SEGMENT_NAME, BYTES/1024/1024, BLOCKS from USER_SEGMENTS ;

SEGMENT_NAME     BYTES/1024/1024     BLOCKS
---------------- --------------- ----------
TAB33                        808     103424

簡単過ぎる演習問題ですいませんデス。先が長いですから、ここでの解説は割愛させて頂きます。

回答例のSQL文はほぼ毎回の連載に登場しますので、もし解説が必要であれば過去の回を探してみてくださいね。


3. 演習2で作成した表領域TBS33のデータ・ファイルが作成されたフルパスとサイズをASMインスタンスに対して問合せて下さい。

[grid@vm11204]$ sqlplus / as sysasm
SQL>
-- ASMディスク・グループDG_HIGH内の全てのASMファイル名とディレクトリを確認
set lines 110 pages 500
col NAME for a20
col ALIAS_DIRECTORY for a16
select NAME, GROUP_NUMBER, FILE_NUMBER, FILE_INCARNATION, ALIAS_DIRECTORY
  from V$ASM_ALIAS
 where GROUP_NUMBER=3 ;

NAME                 GROUP_NUMBER FILE_NUMBER FILE_INCARNATION ALIAS_DIRECTORY
-------------------- ------------ ----------- ---------------- ----------------
ORCL                            3  4294967295       4294967295 Y
DATAFILE                        3  4294967295       4294967295 Y
TBS33.256.856896009             3         256        856896009 N

-- GROUP_NUMBER=3 & FILE_NUMBER=256のASMファイルのサイズを確認
select GROUP_NUMBER, FILE_NUMBER, BYTES, trunc(BYTES/1024/1024)
  from V$ASM_FILE
 where GROUP_NUMBER = 3
   and  FILE_NUMBER = 256 ;

GROUP_NUMBER FILE_NUMBER      BYTES TRUNC(BYTES/1024/1024)
------------ ----------- ---------- ----------------------
           3         256  943726592                    900

-- 任意のASMディスク・グループ内のASMファイルのフルパスとサイズを確認
set linesize 200 pages 5000
col FULL_PATH for a45
select * from (
select CONCAT('+'||GNAME, SYS_CONNECT_BY_PATH(ANAME, '/'))
       FULL_PATH, 
       SYSTEM_CREATED,
       ALIAS_DIRECTORY,
       FNO,
       TRUNC(MBYTES)
  from ( select B.NAME            GNAME,
                A.PARENT_INDEX    PINDEX,
                A.NAME            ANAME,
                A.REFERENCE_INDEX RINDEX,
                A.FILE_NUMBER     FNO,
                A.SYSTEM_CREATED,
                A.ALIAS_DIRECTORY,
                C.TYPE            FILE_TYPE,
                C.BYTES/1024/1024 MBYTES
           from V$ASM_ALIAS     A,
                V$ASM_DISKGROUP B,
                V$ASM_FILE      C
          where A.GROUP_NUMBER     = B.GROUP_NUMBER
            and A.GROUP_NUMBER     = C.GROUP_NUMBER(+)
            and A.FILE_NUMBER      = C.FILE_NUMBER(+)
            and A.FILE_INCARNATION = C.INCARNATION(+)
            and A.GROUP_NUMBER = &ASM_Diskgroup_Number
        )
 START WITH (MOD(PINDEX, POWER(2, 24))) = 0
 CONNECT BY PRIOR RINDEX = PINDEX)
 where SYSTEM_CREATED = 'Y' and ALIAS_DIRECTORY = 'N'
 order by 5 desc ;

FULL_PATH                                   SYS ALIAS_DIRECTORY  FNO TRUNC(MBYTES)
------------------------------------------- --- ---------------- --- -------------
+DG_HIGH/ORCL/DATAFILE/TBS33.256.856896009  Y   N                256           900

ちょっと脱線気味な演習ですが、意外とあまり知られていない(まあ必要なのかも微妙ですが)SQL文を紹介したいと思いまして、用意させて頂いた演習問題です。

一般的にデータ・ファイルのフルパスを確認する際は、データベース・インスタンスに接続して、DBA_DATA_FIELSビュー等を使用すれば確認できると思いますが、今回の演習問題ではASMインスタンスに対してと限定されている点が意地悪いですよね。はい、私は実は意地悪です(笑)

データベース・インスタンスの世界で言うデータ・ファイルは、ASMインスタンスの世界のASMファイルですからV$ASM_FILEビューへ問い合わせれば分かるはずーと思った方、ありがとうございます。半分間違いですね。リファレンス・マニュアルV$ASM_FILEビューを確認して頂くと、ASMファイルのサイズは分かりそうですがファイル名を表す列自体がありませんから、その間違いに簡単に気づいて頂けると思います。そこで、登場するのがV$ASM_ALIASビューなのです。じゃーん。ご存知でしたかね?V$ASM_ALIAS.NAMEがOracle ASMの別名または別名ディレクトリ名を示す通り、正直に言えばASMファイルの実体と言うよりはシンボリック・リンクのようなものなのですがね。

まず回答例の一つ目のSELECT文では、シンプルにV$ASM_ALIASビュー内の情報を問い合わせています。すると3行が戻ってきていますが、ALIAS_DIRECTORY列がYである上の2つはディレクトリ名で、Nである最後の一つがASMファイル名です。このことからも理解できるように、V$ASM_ALIASビューにはディレクトリとASMファイル名が混在しています。ここで一つ必ず理解しておいてほしいこと、それはASMファイルにも番号が振られていると言う事です。このASMファイル番号はASM関連の様々なビューで使用されていますが、上記回答例のV$ASM_ALIASでは「TBS33.256.856896009」のFILE_NUMBER=256 であることが理解できます。もちろん、データベースの世界のデータ・ファイル番号とは一致しませんけどね。そして、「TBS33.256.856896009」をじっと良く見てみると、ピリオド区切りでTBS33のデータ・ファイルで、ASMファイル番号=256と言う事が理解出来ちゃいますね。また、ユーザーが作成したASMファイルは基本的に256番以降の数字が割り当てられますので、ご興味があれば試してみてください。ちなみに、255以下の番号のASMファイルは存在しないのか?と聞かれればNoですが、残念ながらここではこれ以上は触れられません。ごめんなさいね。

次に二つ目のSELECT文は、先に解説したV$ASM_FIELビューを使用してASMファイルのサイズを確認しています。これは簡単なので解説は割愛します。

三つ目のSELECT文で、ようやくフルパス表示が実現しています。これはマニュアルから抜粋したSELECT文を私なりに書き直したと記憶していたのですが、探し直して見たのですが見当たりませんでした。きっと何処かにあるはずです。。。それはまあ良いとして、階層問合せ疑似列を用いた少々難しい構文ですので、是非コピペして使用して頂ければ幸いです。


4. asmcmdユーティリティのiostatコマンドを使用して、ASMディスク・グループDG_HIGHに所属するASMディスクに対するI/O数を2秒間隔で記録して下さい。

[grid@vm11204]$ env | grep -E "ORACLE|PATH"
ORACLE_SID=+ASM
ORACLE_BASE=/u01/app/grid
ORACLE_HOME=/u01/app/grid/product/11.2.0/grid_1
PATH=/u01/app/grid/product/11.2.0/grid_1/bin:/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/grid/bin

[grid@vm11204]$ which asmcmd
/u01/app/grid/product/11.2.0/grid_1/bin/asmcmd

[grid@vm11204]$ asmcmd help iostat
        iostat
        Displays I/O statistics for Oracle ASM disks in mounted disk groups.
        iostat [-et][--io] [--suppressheader] [--region] [-G diskgroup] [interval]
         .... (省略) ....

[grid@vm11204 ~]$ asmcmd iostat --io -G DG_HIGH 2

Group_Name  Dsk_Name      Reads  Writes
DG_HIGH     DG_HIGH_0000  37     5145
DG_HIGH     DG_HIGH_0001  23     5145
DG_HIGH     DG_HIGH_0002  47     5145

Group_Name  Dsk_Name      Reads  Writes
DG_HIGH     DG_HIGH_0000  0.00   0.50
DG_HIGH     DG_HIGH_0001  0.00   0.50
DG_HIGH     DG_HIGH_0002  0.00   0.50

Group_Name  Dsk_Name      Reads  Writes
DG_HIGH     DG_HIGH_0000  0.00   0.50
DG_HIGH     DG_HIGH_0001  0.00   0.50
DG_HIGH     DG_HIGH_0002  0.00   0.50

         .... (省略) ....

さてさてまたもや脱線気味ですが、リバランスの動作を理解するにはデバイスに対するI/O量を分析するのが重要ですので、asmcmdユーティリティのiostatコマンドの実行を体験して頂きました。

このasmcmd iostatコマンドでは「-G」引数としてASMディスク・グループ名を指定することが可能であり、そのASMディスク・グループに所属するASMディスクに限定したI/O量を確認することが出来るのです。これはLinux OSのiostatコマンドと比較して頂ければ、ちょっと便利な感じがしてきますよね。とは言え、%util等の情報は出力されませんから物足りなさを覚える方もいらっしゃるかもしれませんね。

さて、いよいよ本題のリバランスを実行していきましょう。


5. 残存するASMディスク一本を、ASMディスク・グループDG_HIGHへ追加して、強度2でリバランスを実行して下さい。その際、リバランスの進捗状況をV$ASM_OPERATIONビューへ2秒間隔で問合せて下さい。また、以降の演習の為に、ASMディスク・グループDG_HIGHに所属するASMディスクに対するI/O数を2秒間隔で記録しておいてください。

[grid@vm11204]$ sqlplus / as sysasm

SQL> -- どのASMディスク・グループにも属していないASMディスクの検出
set linesize 150 pages 500
col NAME for a12
col HEADER_STATUS for a14
col PATH for a20
select GROUP_NUMBER, DISK_NUMBER, NAME, HEADER_STATUS, PATH
  from V$ASM_DISK
 where GROUP_NUMBER = 0
 order by PATH ;

GROUP_NUMBER DISK_NUMBER NAME         HEADER_STATUS  PATH
------------ ----------- ------------ -------------- ---------
           0           8              FORMER         /dev/sdm1


SQL> -- /dev/sdm1をASMディスク・グループDG_NORMALへリバランス強度で追加
alter diskgroup DG_HIGH add disk '/dev/sdm1' rebalance power 2 nowait ;


[grid@vm11204]$ ### リバランスの進捗状況を2秒間隔で確認
while true; do
  echo "set linesize 150"
  echo "select GROUP_NUMBER, OPERATION, STATE, POWER, ACTUAL,
               SOFAR, EST_WORK, EST_RATE, EST_MINUTES
          from V\$ASM_OPERATION ;"
  sleep 2 ;
done | sqlplus / as sysasm


SQL>
no rows selected

SQL> -- 分析し易いように成形済み
GROUP_NUMBER OPERATION   STATE   POWER ACTUAL SOFAR EST_WORK EST_RATE EST_MINUTES
------------ ----------- ------ ------ ------ ----- -------- -------- -----------
           3 REBAL       WAIT        2      0     0        0        0           0
           3 REBAL       WAIT        2      0     0        0        0           0
           3 REBAL       RUN         2      2     0      715        0           0
           3 REBAL       RUN         2      2    39      715     1168           0
           3 REBAL       RUN         2      2   159      715     2151           0
           3 REBAL       RUN         2      2   279      715     2622           0
           3 REBAL       RUN         2      2   399      715     2822           0
           3 REBAL       RUN         2      2   639      715     3150           0
           3 REBAL       RUN         2      2   715      715        0           0
           3 REBAL       RUN         2      2   715      715        0           0
           3 REBAL       RUN         2      2   715      715        0           0
           3 REBAL       RUN         2      2   715      715        0           0
           3 REBAL       RUN         2      2   715      715        0           0
           3 REBAL       REAP        2      2   715      715        0           0

SQL>
no rows selected

張り切って解説していきましょう。

まずは、どのASMディスク・グループにも所属していないASMディスクを検出し、ALTER DISKGROUP ADD DISK文でASMディスク・グループHIGH_DGへ追加していきます。

その際に、「REBALANCE POWER」句で値(上記の例では2)を指定していますが、これがリバランス強度になります。簡単に言えば、リバランスの強度は数が大きければ大きいほど高速にリバランス処理を実行しようと試みますが、その値の範囲はご存知でしょうか?0~11(「0」がリバランス無し、「1」が最弱で「11」が最強)とお答頂いた方が多いのではないでしょうか。確かに間違ってはいませんが、正しくもありません。なぜならば、演習1で触れさせて頂いた「最大値が1024のASM_POWER_LIMIT」機能が11.2.0.2から登場しているからですね。COMPATIBLE.ASM ディスク・グループ属性を11.2.0.2以上に設定している場合は1~1024(「0」がリバランス無し、「1」が最弱で「1024」が最強)となっていて、リバランス処理を実行するASMインスタンスのARB0プロセスが同時に発行する非同期I/Oの数を指定することになっています。

ちなみに、どの程度の強度でリバランスしたら良いのかは要件や環境に依存してくる部分です。例えば業務処理へ影響なく、ゆっくりとリバランス処理をさせたければ、強度を1や2と言った小さな数字にするべきでしょう。一方、リバランス処理を一気に終わらせたいのであれば、強度を大きくするべきですが、どこまで大きくすれば効果があるのかはASMディスクの本数に依存してしてくるので、リバランスの進捗を見ながら強度を動的に調整していくことをお勧めします。え?動的に調整できるって?って知らない方が多いと思います。リバランス処理中に強度を変更したい場合には特にリバランス処理を止めることなく、「ALTER DISKGROUP<Diskgroup名>REBALANCE POWER<強度> ;」を上書き実行すればOKです。ご興味があれば是非試してみてくださいね。

また、回答例のALTER DISKGROUP ADD DISK文で「NOWAIT」オプションを指定するとリバランス処理の完了を待たずして、即時に制御が戻ってくる動作となります。もしも「WAIT」オプションを指定した場合は、リバランス処理が完了するのを待ってから制御が戻ってきます。ちなみに、「WAIT」オプションを指定て実行中に「Ctrl+C」を入力したらどうなるでしょう?制御は戻ってきますが、リバランスはバックグラウンドで進行を続けますので、ご注意くださいね。


さて、続いての解説は、リバランス処理の進捗を確認する方法です。これにはV$ASM_OPERATIONビューへ問合せを行います。

まず見るべきは、GROUP_NUMBER列とOPERATION列です。対象のASMディスク・グループの番号が入っているか、そして、リバランス操作「REBAL」が実行されているのかを確認しておきましょう。とは言え、本当にリバランス操作が実行されているのかは、その操作のステータス状況を表示するSTATE列の値が「RUN」と表示されていなければなりません。STATE列の値の種類は次の通りです。

  1. WAIT - グループに対して操作を実行していない
  2. RUN - グループに対して操作を実行中
  3. REAP - 操作が停止中
  4. HALT - 管理者による操作の停止
  5. ERRS - エラーによる操作の停止

次に、そのリバランス処理の強度を確認する列がPOWER列とACTUAL列の2つありますが、実際の強度という意味ではACTUAL列を見ておけば問題ありません。POEWR列は、あくまでユーザーが要求した強度であるので参考にしかなりません。そして、V$ASM_OPERATIONビューで最も役立つのが最後の4列であり、操作の進捗状況や残り時間を確認することが出来ます。

  SOFAR : 操作によって今までに移動された割当てユニットの数
  EST_WORK : 操作によって移動する必要がある割当てユニットの推定数
  EST_RATE : 操作によって毎分移動されている割当てユニットの推定数
  EST_MINUTES : 残りの操作に費やされると推定される時間(分)

ちなみに、私の回答例でV$ASM_OPERATIONビューの2秒毎の出力結果を成形したものを見て頂くと、時間が経過する度に「SOFAR:実際に移動した数」が「EST_WORK:移動する必要がある推定数の715」に近づいていくことが確認できるかと思います。データ量が小さくて1分以内でリバランスが完了する環境でしたので、残り時間(分)を示すEST_MINUTES列の値が常に0分になってしまったのは残念でしたが、別の検証では正常に機能することは確認しているので、是非使用してみてくださいね。

ここで、一つ質問を投げかけてみます。もう一度、私の回答例でV$ASM_OPERATIONビューの2秒毎の出力結果を成形したものを見て下さい。SOFARの値が少しずつ増加して最終的にはEST_WORKの「715」と同じ値に達しています。これはリバランス処理によるデータの移動が完了したように理解できますが、それ以降もSTATE列が「RUN」の状態が継続していることが確認できます。実はこの現象を良く問合せを受けるのです。と言う事で、今回はデバイス毎のI/O量のグラフを使って、何をしているのかを簡単に解説してみたいと思います。

shibacho-33-1

上記のグラフは、演習5のリバランス処理中のASMディスク毎のWrite量とRead量を時系列(左から右)で表したものです。具体的な数字は伏せておりますが、各グラフの縦スケールは全て同一値に合わせておきました。上の3つのグラフで表されている/dev/sdj1、/dev/sdk1、/dev/sdl1は元々ASMディスク・グループに含まれていたASMディスクで、一番下のグラフの/dev/sdm1が新規に追加した空のASMディスクです。

リバランス処理は、既存データを新規に追加した空のASMディスクに対して分散配置し直す処理ですから、既存の3本のASMディスクからほぼ同じ量のデータを読みんで、新規のASMディスクへ書き込んでいることがグラフから読み取ることができると思います。分かりやすいですよね!このフェーズをリバランス・フェーズと呼び、V$ASM_OPERATIONビューで、SOFARの値がEST_WORKの値へ近づいていっている最中なのです。

グラフには緑色の線を2本引かせて頂きましたが、一本目(左側)の緑色の線のタイミングからはI/Oの特徴が変化していますよね。上の2本のASMディスクでREADとWRITEが行われていて、3本目と4本目のASMディスクには何もI/Oが発生していないでしょう。さらに、二本目の緑色の線以降では、先ほどまでI/Oが発生していた上の2本のASMディスクには何もI/Oが発生しておらず、3本目のASMディスクにだけREADとWRITEが発生している。なんだか、3本目のASMディスクからデータを読んで、そのまま3本目に書き込んでいるように見えます。実はそのとおりなのです!自分自身のデバイスに閉じてデータの読書きを行っているのです。このフェーズをコンパクション・フェーズと呼びます。V$ASM_OPERATIONビューで、SOFARの値がEST_WORKの値に達したのに、中々リバランス処理が完了しない際中は、このコンパクション・フェーズ中だと認識して下さい。


色々疑問が山積みだと思いますので、整理していきましょう。

リバランス処理は、ASMディスク間でデータを移動するリバランス・フェーズと、ASMディスク内でデータを移動するコンパクション・フェーズがあります。前者のリバランス・フェーズは、ASMのミラーリング、ストライピングを実現する上で必要不可欠な処理で有ることは、「第31回 ASMのストライピングとリバランスによるI/O性能の向上」で体験済みかと思います。ただし、リバランスではデータ・ファイル単位で均等に分散し直すので、「データ・ファイルの後半何MBだけ新規ASMディスクへ移動」と言った移動の仕方ではありません!これではI/O性能が向上しないのは明らかですしね。説明が難しいですが、既存ASMディスクから新規ASMディスクへデータを移動すると、新規ASMディスク側は元々空っぽですからディスクの先頭から順番にデータが書き込まれていきます。一方、既存ASMディスク側は新規ASMディスクへ移動したデータは削除していきますから、リバランス・フェーズが終わった段階では歯抜け状態になっているのが想像できるかと思います。

このデータの歯抜け状態を解消する為に、もう一つのフェーズであるコンパクション・フェーズの処理で、ASMディスク内に閉じて、データの移動が実行されるのですね。

つまり、もう一度I/Oグラフを見て頂くと、リバランス・フェーズは、既存3本のASMディスクからデータを読んで、新規ASMディスクへデータを書き込んでいます。そして、一本目の緑の線でそのリバランス・フェーズが完了し、既存の2本のASMディスクのコンパクション・フェーズが開始。ここで何故、既存3本のASMディスクじゃなくて2本なのか?答えは簡単。リバランス強度を「2」に設定したからですね。よって、もし高速にリバランス処理を終えたいのであれば、本来は既存ASMディスク本数以上の強度に設定するかもですね。ちなみに、こっそり情報ですが、多くのFlashデバイスやHDDを搭載する最新のExadataにおいては、今回ご紹介したコンパクション処理は実行されないように設定されていたりします。

最後に、性能検証時に私が良く使用しているdstatコマンドの引数指定を簡略化するシェルをご紹介しておきましょう。正直、エラーハンドリングとかほとんど無いに等しいので、ご利用される際は自己責任でお願いします。

asmcmdユーティリティのiostatコマンドやら、OSのiostatコマンドは、縦にデバイス名が並ぶ固まりが指定秒数毎に出力されるので、グラフ化するのに一苦労だと思いますが、dstatコマンドであれば、CPUやデバイスを横に並べて指定秒数毎に一行しか出力されませんので、非常に扱い易い形式となります。とは言え、引数の指定や若干ややこしいので、そこを簡単にしてみたというだけです。

./dstat_shibacho.sh
===================================================
#!/bin/sh

if [ $# -eq 0 -o "$1" = "help" -o "$1" = "-h" ]; then
  echo "sh ./dstat_shibacho.sh <INTERVAL_SEC> <BOTH | CPU | DISK> \"<DISK_LIST>\""
  echo "example1:  sh ./dstat_shibacho.sh  1  CPU"
  echo "example2:  sh ./dstat_shibacho.sh  5  DISK  \"/dev/sdb1 /dev/sdc1\""
  echo "example3:  sh ./dstat_shibacho.sh 60  BOTH  \"/dev/sd[bcdef]1\""
  exit 
fi

INTERVAL=$1
OPTION=`echo $2 | tr 'a-z' 'A-Z'`
DISKLIST=$3
LOGDIR=./
TARGETHOST=`hostname`
STARTTIME=`date +%Y%m%d_%H%M%S`
OPTIONS="-t"
### CPU Setting
if [ "${OPTION}" = "CPU" -o "${OPTION}" = "BOTH" ] ; then
  OPTIONS="${OPTIONS}" "-c -C"
  CPUS=`cat /proc/cpuinfo|grep processor|awk '{print $3}'`
  i=0
  for cpus in ${CPUS}; do
    if [ ${i} -eq 0 ]; then
      OPTIONS=${OPTIONS}" "${cpus}
    else
      OPTIONS=${OPTIONS}","${cpus}
    fi
    i=`expr ${i} + 1`
  done
  OPTIONS=${OPTIONS}",total"
fi

### Disk Setting
if [ "${OPTION}" = "DISK" -o "${OPTION}" = "BOTH" ] ; then
  OPTIONS=${OPTIONS}" -d -D"
  DISKS=0
  for disks in ${DISKLIST}; do
    DISKS=`expr ${DISKS} + 1`
  done
  if [ ${DISKS} -eq 1 ]; then
    DISKS=`ls ${DISKLIST} | sed -e "s@/dev/@@g"`
  else
    DISKS=`echo ${DISKLIST} | sed -e "s@/dev/@@g"`
  fi

  i=0
  for disks in ${DISKS}; do
    if [ ${i} -eq 0 ]; then
      OPTIONS=${OPTIONS}" "${disks}
    else
      OPTIONS=${OPTIONS}","${disks}
    fi
    i=`expr ${i} + 1`
  done
  OPTIONS=${OPTIONS}",total"
fi

### LogFile Setting
OPTIONS=${OPTIONS}" -p -s  -y"
OPTIONS=${OPTIONS}" --output "${LOGDIR}"/dstat_"${TARGETHOST}"_"${STARTTIME}".log"

### Execute
/usr/bin/dstat ${OPTIONS} ${INTERVAL}
===================================================
$ sh ./dstat_shibacho.sh 2 DISK "/dev/sd[jklm]1"

----system---- --dsk/sdj1----dsk/sdk1----dsk/sdl1----dsk/sdm1---dsk/total- ---procs--- ----swap--- ---system--
  date/time   | read  writ: read  writ: read  writ: read  writ: read  writ|run blk new| used  free| int   csw
29-08 18:32:20|   0  2048B:   0  2048B:   0  2048B:   0     0 :   0    84k|  0   0 0.5|   0  1024M|1910  3492
29-08 18:32:22|   0  2048B:   0  2048B:8192B 2048B:  32k    0 :  84k   46k|0.5   0 0.5|   0  1024M|2029  3558
29-08 18:32:24|6144B   12k:6144B   12k:6144B   12k:6144B 1042k:  56k 1078k|0.5   0 0.5|   0  1024M|2072  3694
29-08 18:32:26|   0  8192B:2048B 8192B:   0  8192B:   0  2048B:2048B  124k|0.5   0 0.5|   0  1024M|2016  3563
29-08 18:32:28|  16M  400k:  16M  406k:  16M  404k:8448B   16M:  47M   17M|0.5 1.0 1.5|   0  1024M|3777  6066
29-08 18:32:30|  19M   12k:  20M   66k:  20M   66k:2048B   50M:  58M   50M|  0 0.5 0.5|   0  1024M|3692  6112
29-08 18:32:32|  22M  122k:  22M  122k:  21M  120k:   0    65M:  65M   65M|1.0 0.5 0.5|   0  1024M|4357  7168
29-08 18:32:34|  21M  130k:  21M  130k:  21M  132k:   0    63M:  63M   63M|1.0 0.5 0.5|   0  1024M|4166  7005
29-08 18:32:36|  22M  124k:  22M  124k:  22M  124k:2048B   65M:  65M   65M|  0 1.0 0.5|   0  1024M|4254  7164
29-08 18:32:38|  22M   68k:  22M   68k:  22M   66k:   0    66M:  66M   66M|0.5 0.5 0.5|   0  1024M|4331  7075
29-08 18:32:40|  24M   13M:  24M   13M:  12M  126k:   0    33M:  60M   59M|0.5   0 0.5|   0  1024M|4213  7024
29-08 18:32:42|  29M   29M:  28M   29M:   0    62k:   0     0 :  57M   58M|0.5 0.5 1.5|   0  1024M|4090  6710
29-08 18:32:44|  30M   30M:  30M   30M:   0    62k:   0  6144B:  60M   60M|  0 1.0 0.5|   0  1024M|4163  6855
29-08 18:32:46|  18M   18M:  18M   18M:  21M   21M:2048B 4096B:  57M   57M|0.5 0.5 0.5|   0  1024M|3974  6627
29-08 18:32:48|2048B   32k:2048B   32k:  49M   49M:2048B    0 :  49M   49M|2.5   0 0.5|   0  1024M|3689  6236
29-08 18:32:50|  10k   20k:  10k   20k:  20M   20M: 161k 4096B:  20M   20M|1.5   0 7.5|   0  1024M|2835  4865
29-08 18:32:52|2048B 4096B:2048B 4096B:2048B 4096B:2048B 2048B:8192B   56k|  0   0 0.5|   0  1024M|2037  3647
29-08 18:32:54|   0  4096B:   0  4096B:   0  6144B:   0  6144B:   0    50k|0.5   0 0.5|   0  1024M|2000  3576

さて、ASMのリバランスの動作を解説させて頂きましたが、いかがでしたでしょうか?

演習5をもう少し分割して解説させて頂ければ良かったのではと反省しておりますが、ASMのリバランス処理が実際にどのようなことをしているのかを理解して頂くことで、少し安心して頂けたのではないかと思っています。特に、V$ASM_OPERATIONビューのSOFAR値がEST_WORKS値に達したのにリバランス処理が完了しないと非常に不安になりますが、iostatやdstatコマンドでASMディスクのI/O量を確認することで、コンパクション処理が実行されているか否かを判断できるスキルを身につけて頂けたかと思います。この辺りの動作に関しては、サポート契約をお持ちの方はDoc ID 1274322.1 も参照して頂けると興味深い情報が載っているので参考にしてみてくださいね。

今回も最後まで体験して頂きましてありがとうございました。次回以降もどうぞよろしくお願い致します。

しばちょう先生の試して納得!DBAへの道 indexページ▶▶