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

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

前回は X$BH 表のSTATE列を見ることによって、バッファ上のオブジェクトの
状態が把握できる事を確認した。今回は「単一サーバ」、「単一セッション」
の環境でSELECT、INSERT、UPDATE処理時にデータベース・バッファ上のオブ
ジェクトのステータスがどのように変化にするのかを見ていきたい。

検証環境とテーブル構成は以下通りである。

*************************************************************
◆環境
Linux 2.4.2-2
Oracle9i EE Release 9.2.0.1.0

◆テーブル構成

SQL> desc test
 Name      Type
 --------- ------------------
 ID1       NUMBER
 ID2       NUMBER
 TEXT      VARCHAR2(2000)

※ID1にINDEX(TEST_IDX)を付与

では、最初に単純なSELECT文の場合のステータスの変化を見てみよう。

*************************************************************
◆select 文を実行

SQL> select * from test ;

◆データベース・バッファの状態を取得

SQL> select
o.object_name
,decode(state,0,'free',1,'xcur',2,'scur',3,'cr', 4,'read',5,'mrec'
,6,'irec',7,'write',8,'pi') state
, blsiz , count(*) blocks
from x$bh b , dba_objects o
where b.obj = o.data_object_id
and b.ts# > 0
and o.object_name = 'TEST'
group by o.object_name, state, blsiz

◆問い合わせの結果

OBJECT_NAME                    STATE      BLSIZ     BLOCKS
------------------------------ ----- ---------- ----------
TEST                           xcur        8192          6

ブロックの状態はXCUR、他のインスタンスとは共有していない(排他)のカ
レント・モードであることを示している。つまり、最新のブロック・イメー
ジのみがデータベース・バッファ上に載っている状態である。ちなみに、今
回はRACの環境ではないのでSCUR(共有カレント)になる事はない。

同じセッションからはINSERT処理を行なっても同様の状態である。別のセッ
ションからのアクセスがないので、読み取り一貫性も何もないのであるから
当然の結果と言える。

ただし、不思議なことにUPDATE処理ではCRブロックが出来る。

*************************************************************
◆UPDATE処理を実行

SQL> update test set id1 = 1 where id2 =2;

◆問い合わせの結果

OBJECT_NAME                    STATE      BLSIZ     BLOCKS
------------------------------ ----- ---------- ----------
TEST                           xcur        8192          6
TEST                           cr          8192          1

ちなみにCRブロックとは?
CRブロックとは読み取り一貫性を保証する為に、作成される読み取り専用の
イメージ・ブロックである。

なぜ更新時にだけCRブロックが作成されるのか?しかも単一セッションでの
更新でCRブロックを作らなくてもいいと思われる状態である。これに関して
は今後検証を進めていく中で明らかにして行きたいと思う。

では次に、データベース・バッファ上のダンプを取得して、XCURとCRの各ブ
ロック内のデータ部を見てみよう。

ダンプのデータを、データベース・バッファ上のデータの突合せを行なう為に
X$BH 表からBA(バッファドレス)を取得する。データベース・バッファのダ
ンプ取得の詳細に関してはバックナンバー(Oracle 9iに関する検証 その10)
を参照して頂きたい。

*************************************************************
◆データベース・バッファの状態を取得
 ※ブロック番号(dbarfil,dbablk)とブロックアドレス(BA)を取得

SQL> select
o.object_name
,decode(state,0,'free',1,'xcur',2,'scur',3,'cr', 4,'read',5,'mrec'
,6,'irec',7,'write',8,'pi') state
, dbarfil
, dbablk
, ba
from x$bh b , dba_objects o
where b.obj = o.data_object_id
and b.ts# > 0
and o.object_name = 'TEST'
group by o.object_name, state, blsiz
, ba, dbarfil, dbablk

◆問い合わせの結果

OBJECT_NAME   STATE    DBARFIL     DBABLK BA
------------- ----- ---------- ---------- --------
TEST          xcur           9      18720 54DD4000
TEST          xcur           9      18719 54DD6000
TEST          xcur           9      18718 54DD8000
TEST          xcur           9      18717 54DDA000
TEST          xcur           9      18715 54DE2000

TEST          xcur           9      18716 54C1E000
TEST          cr             9      18716 54DDC000

データファイル(DBARFIL)、ブロック番号(DBABLK)が同じなので、下から
2行がUPDATE対象のBLOCKであることが分かる。

◆ダンプの取得

SQL> alter session set events 'immediate trace name buffers level 6';

◆XCURブロック
更新後データ:(列1,列2,列3) = (2,2,’insight)

tl: 17 fb: --H-FL-- lb: 0x2  cc: 3
col  0: [ 2]  c1 02
col  1: [ 2]  c1 03
col  2: [ 7]  69 6e 73 69 67 68 74
tab 0, row 2, @0x1f65

◆CRブロック
更新前データ:(列1,列2,列3) = (1,2,’insight)

tl: 17 fb: --H-FL-- lb: 0x0  cc: 3
col  0: [ 2]  c1 03
col  1: [ 2]  c1 03
col  2: [ 7]  69 6e 73 69 67 68 74

ダンプのデータ部分を見てみると、当然であるが、カレント・ブロック(XCUR)
が最新(更新後)のデータで、CRが更新前のデータとなっている。ちなみに、
以下の様に、UPDATE処理を繰り返していくとCRブロックはどんどん増えていく。

*************************************************************
OBJECT_NAME     STATE    DBARFIL     DBABLK BA
--------------- ----- ---------- ---------- --------
・
TEST            xcur           9      18716 54C5E000 <- XCURのDBA
TEST            cr             9      18716 55BA4000

OBJECT_NAME     STATE    DBARFIL     DBABLK BA
--------------- ----- ---------- ---------- --------
・
TEST            xcur           9      18716 54C54000 <- XCURのDBA
TEST            cr             9      18716 54C5E000 <- CRに変化
TEST            cr             9      18716 55BA4000

OBJECT_NAME     STATE    DBARFIL     DBABLK BA
--------------- ----- ---------- ---------- --------
・
TEST            xcur           9      18716 54C50000
TEST            cr             9      18716 54C54000 <- CRに変化
TEST            cr             9      18716 54C5E000
TEST            cr             9      18716 55BA4000
*************************************************************

UPDATE処理を行なう度に、カレント・ブロック(XCUR)がCRブロックになり、
新規のカレント・ブロックが作成されている様子がよく分かる。

CRブロックは更新の度にどんどん増えていく。これでは一つのオブジェクトの
更新が頻繁に行われる環境では、データベース・バッファの領域が食い尽くさ
れてしまいパフォーマンスが低下してしまうのでは!

調べてみると、以下の隠しパラメータで制限されているようである。パラメー
タ値はデフォルトで"6"となっている。

_db_block_max_cr_dba = 6

今回はUPDATE処理でCRブロック作成されたが、実はCRブロックが作成されない
ケースも存在する。それはどのような場合か?これに関しては次回検証する。

以上、沖縄で焼けた肌がすごい!?茅ヶ崎にて