続 X$BH に関する検証 その10

<続 X$BH に関する検証 ~その10~>
ペンネーム ちょびひげ

今回も前回に引き続きRACの環境で、データベース・バッファ上のオブジェク
トの状態(ステータス)の変化を見ていきたい。

前回の検証では、以下の競合を見た。

◇Read/Read の競合
◇Read/Write の競合
◇Write/Readの競合

Read(NODE1で読込)/Write(NODE2で書込み)の競合ではNODE1 の共有モードの
カレント・ブロック(SCUR)が読取一貫性のブロック(CR)にコンバート(
ロックダウン)される状態をみた。今回はWrite/Writeの競合で発生するロッ
クダウン時の状態(ステータス)の変化を見ていく。

今回のポイントは、RACチューニングで重要となる以下2つの内容である。

1. Write/Writeの競合で発生するロックダウンは特に負荷の高い処理である。
   つまり、これを減らす事がRACチューニングでの1つのポイントとなる。

2. Write/Writeの競合ではロックダウンに伴なって、PI(Past Image)が作
   成される。このブロックをデータベース・バッファ上にあまり残さない事
   が重要となる。
   ※PIに関しては非常に分かりづらい内容なので、検証の中で詳しく説明し
     ていきたい

以下、負荷の高いロックダウン発生の原因、また、ロックダウンに伴うPIブ
ロック作成などのオーバヘッドになる動きに関して、検証を通して見ていき
たい。

今回の検証環境も以下の通りである。

*************************************************************
□環境(2ノードのRAC構成)
Linux 2.4.9-e.9.30ml
Oracle9i Release 9.2.0.3.0

□テーブル構成

SQL> desc TEST

 Name      Type
 --------- ------------------
 ID1       NUMBER
 ID2       NUMBER
 TEXT      VARCHAR2(2000)

□ID1にINDEX(TEST_IDX)を付与

□入っているデータは以下の3件

       ID1        ID2 TEXT
---------- ---------- --------------------
         1          1 insight
         2          2 insight
         3          3 insight

まずは、NODE1からUPDATE(Write)を実行する。

**********************************[Write/Writeの競合その1]***
□NODE1でUPDATE(Write)を実行

SQL> update test set text='aaaaa' where id1=2;

<<NODE1の状況>>

OBJECT_NAME   STATE               DBABLK BA        X_TO_NULL        TCH
------------- --------------- ---------- -------- ---------- ----------
TEST          scur                   257 5E5B6000          0          1
TEST          xcur                   258 5E5AC000          0          1
TEST_IDX      scur                  1170 5E5AE000          0          1

ここまでは前回のWrite/ReadのUPDATE(Write)と同様の結果である。
では、次にNODE2でもUPDATE(Write)を行ってみる。

**********************************[Write/Writeの競合その2]***
□NODE2でUPDATE(Write)を実行

SQL> update test set text='bbbbb' where id1=3;

<<NODE1の状況>>

OBJECT_NAME   STATE               DBABLK BA        X_TO_NULL        TCH
------------- --------------- ---------- -------- ---------- ----------
TEST          scur                   257 5E5B6000          0          1
TEST          pi                     258 5E5AC000          1          1
TEST_IDX      scur                  1170 5E5AE000          0          1

<<NODE2の状況>>

OBJECT_NAME   STATE               DBABLK BA        X_TO_NULL        TCH
------------- --------------- ---------- -------- ---------- ----------
TEST          scur                   257 5E5B4000          0          1
TEST          xcur                   258 5E5AC000          0          1
TEST_IDX      scur                  1170 5E5AE000          0          1

冒頭でも述べたようにPIはWrite/Writeの競合時のみに発生する。

NODE1の状況に注目して頂きたい!Past Image(PI)が作成されている。この
ブロックはWrite/Writeの競合が発生した場合に、他NODEに排他のカレント・
ブロックの権限を移譲する必要がある。そのために、カレント・ブロックを
ロックダウンしてCRブロックにする。これが第2のロックダウンである。

ここでいう第2というのは、前回はRead/Write の競合では共有のカレント・
ブロック(scur)からCRブロックへのロックダウンであったが、今回は、排
他のカレントブロック(xcur)からのロックダウンであることを示している。

ここで重要になってくるのは排他のカレント・ブロックからのロックダウン
では、カレントブロックコピー、つまり最新のブロック情報を持つPast Image
(PI)が作成される点である。万一、カレント・ブロックの権限を移譲した
先のNODE(ここではNODE2)でトラブルが発生した場合でも、自NODEのPIに対
してトラブルが発生したノードのREDOログを適用することにより、迅速なリ
カバリが可能な為である。

もし、自NODEにPast Image(PI)がない場合はどうなるであろうか?当然、
最後にディスクに書き込まれたデータに対してREDOログを適用することにな
る。つまり、自ノードで更新した内容がディスクに書き込まれていない場合
は、自NODEと他ノードの2つのREDOログを適用する必要が出てくる。このよう
に、主にリカバリの時間を高速化するための役割をPast Image(PI)が果た
しているわけである。

もう少し、先程の検証結果を見てみよう。最初のロックダウンでPast Image
(PI)のX_TO_NULLが1にカウントアップされている。

NODE2では、共有のカレント・ブロックであるインデックス(TEST_IDX)から
、更新対象のROWIDを特定して、該当ブロックをNODE1からインターコネクト
経由で取得する。最後に、カレント・ブロックに対して更新を行ってUPDATE
が完了でする。

では、再度NODE1でUPDATE(Write)を行ってみよう。

**********************************[Write/Writeの競合その3]***
□NODE1でUPDATE(Write)を実行

SQL> update test set text='ccccc' where id1=2;

<<NODE1の状況>>

OBJECT_NAME   STATE               DBABLK BA        X_TO_NULL        TCH
------------- --------------- ---------- -------- ---------- ----------
TEST          scur                   257 5E5B6000          0          1
TEST          xcur                   258 5E5A6000          1          1
TEST          pi                     258 5E5AC000          1          1
TEST_IDX      scur                  1170 5E5AE000          0          2

<<NODE2の状況>>

OBJECT_NAME   STATE               DBABLK BA        X_TO_NULL        TCH
------------- --------------- ---------- -------- ---------- ----------
TEST          scur                   257 5E5B4000          0          1
TEST          pi                     258 5E5AC000          1          1
TEST_IDX      scur                  1170 5E5AE000          0          1

まず、NODE2の状況であるが、1つ前(Write/Writeの競合その2)のNODE1の状
況と全く同じである。

NODE1に関しても、主な変化は1つ前(Write/Writeの競合その2)のNODE2の状
況と同じである。

ここでのポイントはNODE1のカレント・ブロックとPast Image(PI)の内容が
異なっている点である。Past Image(PI)はあくまで、他のNODEから排他の
カレント・モードでのブロック要求があった際に、ロックダウンが発生して
初めて、カレント・ブロック(XCUR)のコピーが作成される。

次に、NODE2で再度UPDATE(Write)を行ってみる。ここでは特にX_TO_NULLと
TCHの値に注目して頂きたい。

**********************************[Write/Writeの競合その4]***
□NODE2でUPDATE(Write)を実行

SQL> update test set text='ddddd' where id1=3;

<<NODE1の状況>>

OBJECT_NAME   STATE               DBABLK BA        X_TO_NULL        TCH
------------- --------------- ---------- -------- ---------- ----------
TEST          scur                   257 5E5B6000          0          1
TEST          cr                     258 5E5A6000          2          1
TEST          pi                     258 5E5AC000          1          1
TEST_IDX      scur                  1170 5E5AE000          0          2

<<NODE2の状況>>

OBJECT_NAME   STATE               DBABLK BA        X_TO_NULL        TCH
------------- --------------- ---------- -------- ---------- ----------
TEST          scur                   257 5E5B4000          0          1
TEST          xcur                   258 5E5AA000          1          1
TEST          pi                     258 5E5AC000          1          1
TEST_IDX      scur                  1170 5E5AE000          0          2

NODE1のカレント・ブロックがCRブロックにロックダウンして、X_TO_NULL、
TCHの値がカウントアップされている(BAが5E5A6000のブロック)。また、こ
れに伴って。Past Image(PI)の内容が更新されている。ただし、Past Image
(PI)のX_TO_NULL、TCHの値はカウントアップされていない。

では、なぜTCHがカウントアップされないのか?
Past Image(PI)の役割は、あくまでもリカバリ時に使用されるブロックの
ため、再利用性は低い。また、今回の検証では強制的にWrite/Writeの競合を
発生させているが、本来、Past Image(PI)=Write/Writeの競合と考えれば
、PIがデータベース・バッファ上にあるほどWrite/Writeの競合が発生してお
り、パフォーマンス上は望ましくないことが分かる。前回の検証でもWrite/W
riteの競合でのパフォーマンスの劣化は顕著に現われた。このような観点か
らはTCHの値がカウントアップされないのは納得がいく。
※TCHに関する詳しい検証は “Oracle9iに関する検証8~” をご参照ください。

では、またまたNODE1でUPDATE(Write)を行ってみる。

**********************************[Write/Writeの競合その5]***
□NODE1でUPDATE(Write)を実行

SQL> update test set text='eeeee' where id1=2;

<<NODE1の状況>>

OBJECT_NAME   STATE               DBABLK BA        X_TO_NULL        TCH
------------- --------------- ---------- -------- ---------- ----------
TEST          scur                   257 5E5B6000          0          1
TEST          xcur                   258 5E5A4000          2          1
TEST          cr                     258 5E5A6000          2          1
TEST          pi                     258 5E5AC000          1          1
TEST_IDX      scur                  1170 5E5AE000          0          3

<<NODE2の状況>>

OBJECT_NAME   STATE               DBABLK BA        X_TO_NULL        TCH
------------- --------------- ---------- -------- ---------- ----------
TEST          scur                   257 5E5B4000          0          1
TEST          cr                     258 5E5AA000          2          1
TEST          pi                     258 5E5AC000          1          1
TEST_IDX      scur                  1170 5E5AE000          0          2

NODE1の排他のカレント・ブロック(XCUR)のX_TO_NULLの値が2から始まって
いる。なぜか?なぜか?と考えても良い検証案は浮かびませんでした。

ちなみに、この後も、Write/Writeの競合を繰り返すとカレント・ブロック(
XCUR)のX_TO_NULLの値が増えつづけていった。

しかし、今回のインデックス検索でのUPDATEを全件検索に変えて試したとこ
ろ、上記の様にX_TO_NULLの値が2から始まる事はなく、X_TO_NULLの値が増え
続ける事は無かった。

Oracleのマニュアルにも以下のような記載があるので、この列の値自体が正
しいという保証はないのちょっと気になるところである。実際にOracleの10g
からは無くなっている。

<Oracleのマニュアルより抜粋>---------------------------------------
X_TO_NULL:
別のインスタンスとの競合による排他モードからNULL モードへのPCM ロック
変換の回数。この列は廃止されたが、旧バージョンとの互換性を保つために
残されている
---------------------------------------------------------------------

では、最後にデータベース・バッファ上のPast Image(PI)を全て消して、
続X$BHに関する検証を終わりにしたい。

*************************************************************
□NODE1でチェックポイントを発生させる

SQL> alter system checkpoint;

システムが変更されました。

Past Image(PI) → CRブロック

以上、快晴の茅ヶ崎にて