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

∽ 前回の検証の訂正 ∽

申し訳ありません。前回の検証で取得したダンプの結果が間違っていました
ので訂正します。
【正】が正しく
【誤】が前回間違っていた部分です。

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

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

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

◆CRブロック
【正】更新後データ:(列1,列2,列3) = (2,2,’insight)
【誤】更新後データ:(列1,列2,列3) = (1,2,’insight)

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

┏─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━┓
●【 Oracle 検証生活 】 ●
┗─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━┛
<続 X$BH に関する検証 ~その3~>
ペンネーム ちょびひげ

前回は「単一サーバ」、「単一セッション」でX$BH表のSTATE列の情報を見る
事により以下の点を確認した。

・SELECT、INSERT処理を行ってもCRブロックは作成されない。
・UPDATE処理を行った場合にはCRブロックが作成される。

今回は同じUPDATE処理でもCRブロックが作成されないケースが存在するので、
その状況を見てみよう。ちなみにDELETE処理は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)を付与

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

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

前回のUPDATE処理では以下のSQL文を実行した。

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

このSQLではWHERE句の条件として”ID2″列を指定している。”ID2″列にはイン
デックスが作成されていないので、全件検索を行っての更新処理となってい
る。

そこで、今回はWHERE句の条件として、インデックスが作成されている”ID1″
列を指定して、インデックス検索による更新を行ってみる。

*************************************************************
◇UPDATE処理を実行

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

※インデックスが使用されるようにWHERE句の条件にID1列を指定している

◇データベース・バッファ上の状態

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
     , count(*) BLOCK
     from x$bh b , dba_objects o
     where b.obj = o.data_object_id
       and o.object_name = 'TEST%'
     group by o.object_name, state

OBJECT_NAME          STATE     BLOCKS
-------------------- ----- ----------
TEST                 xcur           2
TEST_IDX             xcur           1

ご覧の通りCRブロックは作成されない。インデックスも1ブロックだけデータ
ベース・バッファ上にある状態である。なぜか???。。。

ちなみに、前回行った全件検索での更新処理でも、更新対象のデータが無い
場合はCRブロックは作成されない。

*************************************************************
更新対象がない全件検索でUPDATE処理を行った時のデータベース・バッファ
の状態

SQL> update test set id1=3 where id2=5;
※ID2 にはインデックスはなく、ID2=5 のデータは存在しない。

0行が更新されました。

OBJECT_NAME          STATE    DBARFIL     DBABLK BA      
-------------------- ----- ---------- ---------- --------
TEST                 xcur           1      70913 54D28000
TEST                 xcur           1      70914 54D20000

いままでのCRブロックが作成されるケースは以下の通りである。

CRブロックが作成されるケース(単一セッション)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                   UPDATE              SELECT    INSERT
----------------   ------------------- --------- --------
全件検索           ○(更新対象あり)  ×        ―
インデックス検索   ×                  ×        ―

「単一のセッション」の場合は全件検索のUPDATE処理でのみCRブロックが作
成されるということになる。

つまり、なぜ全件検索のUPDATE処理時にCRブロックが出来るか?が疑問であ
る。

本来、CRブロックは読取一貫性のブロックではあるが、「単一セッション」
にもかかわらずCRブロックが出来る理由は、CRブロックを読みに行く為では
なく、ロールバック情報の作成やロックの機能を満たす必要がある為ではな
いだろうか?

インデックス検索の更新ではCRブロックが出来ないのは、インデックスから
更新対象のROWIDを特定する事ができるので、行単位で更新処理を行なう為に
CRブロックを作る必要がないのかも知れない。

では最後に、カレント・ブロックの更新の仕組みが全件検索とインデックス
検索の場合で大きく異なっている点を見てみる。

以下は、インデックス検索時のカレント・ブロックのバッファ・アドレス(
BA:データベース・バッファ上での場所)の変化である。
*************************************************************
インデックス検索での更新時:

【更新前】

OBJECT_NAME          STATE   DBABLK BA      
-------------------- ----- -------- --------
TEST                 xcur     18716 54D0E000  ← 更新対象ブロック
TEST_IDX             xcur     18724 54D04000

【更新後】

OBJECT_NAME          STATE   DBABLK BA      
-------------------- ----- -------- --------
TEST                 xcur     18716 54D0E000  ← 更新対象ブロック
TEST_IDX             xcur     18724 54D04000     ※BAに変化なし

カレント・ブロックのアドレス(BA)が変化していない。つまり、直接カレン
ト・ブロック内のデータの更新を行っている。

次に全件検索時のXCURブロックのバッファ・アドレス(BA)の変化をみて頂き
たい。

*************************************************************
全件検索での更新時:

【更新前】

OBJECT_NAME          STATE   DBABLK BA      
-------------------- ----- -------- --------
TEST                 xcur     18717 54C3A000  ← 更新対象ブロック

【更新後】

OBJECT_NAME          STATE   DBABLK BA      
-------------------- ----- -------- --------
TEST                 xcur     18717 551F2000  ← 更新対象ブロック
TEST                 cr       18717 54C3A000     ※BAに変化あり
                                       ↑
                                変更前のカレント・ブロックのBA

カレント・ブロックのアドレス(BA)が変化している事が分かる。また、更
新前にカレント・ブロックだったアドレス(BA)には、CRブロックとなって
いる。つまり、全件検索時の更新処理の流れは以下のようになる。

(1)54C3A000(BA)にあったカレント・ブロック(XCUR)が 551F2000(BA)
     にコピーされる。
(2)元のカレント・ブロックがCRブロックとなる。
(3)XCURへの更新処理を行なう。

次回は「単一サーバ」、「複数セッション」の場合の動きを見ていきたい。

以上、日暮れ間際の茅ヶ崎にて