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

投稿日: 2003年11月19日

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

今回はまず前回の検証の補足を行いたい。

前回の検証ではUPDATE処理を行う事により、テーブルとインデックスのブロ
ックに対する更新を行い、テーブルのトランザクション・エントリからUNDO
ブロックのアドレスとUNDOエントリのレコード番号がを取得してUNDOエント
リを見ていった。

補足させて頂きたい点は、テーブルとインデックスではトランザクション・
エントリの Uba が異なる点である。

例えば、全く更新を行ってない場合は以下の様にトランザクション・エント
リは存在しない。

[テーブル・ブロックのItl]
Itl         Xid                  Uba         Flag  Lck        Scn/Fsc

[インデックス・ブロックのItl]
Itl         Xid                  Uba         Flag  Lck        Scn/Fsc

ここでUPDATEを実行するとそれぞれのブロックにトランザクション・エ
ントリが出来る。

[テーブル・ブロックのItl]

Itl         Xid                  Uba         Flag  Lck        Scn/Fsc
0x01 0x0002.009.00029f0a  0x00800cf8.098c.02  ----    2  fsc 0x0000.00000000

[インデックス・ブロックのItl]

 Itl         Xid                  Uba         Flag  Lck        Scn/Fsc
0x01 0x0002.009.00029f0a  0x00800ca4.098c.04  ----    4  fsc 0x0000.00000000
                             ↑           ↑[最後のUNDOレコード番号(16進)]
                            [UNDOブロックのDBA(16進)]

前回はテーブルのトランザクション・エントリしか見なかったが、実際はテ
ーブルとインデックスそれぞれの Uba が異なっている事が分かる。理由は、
CRブロックを作成する際は、トランザクション単位ではなく、ブロック単位
でUNDOエントリを取得する必要があるためです。

ちなみにトランザクション単位の最後のUNDOエントリの位置はv$transaction
表から取得可能である。

SQL> select UBAFIL , UBABLK, UBAREC from v$transaction;

    UBAFIL     UBABLK     UBAREC
---------- ---------- ----------
         2       3488          1

以上、と言いたいところであるが、ちょっと短いので、INSERT時のUNDOエン
トリの情報量に関して面白い現象を見て頂きたい。

9i になって自動UNDO管理になり、UNDOセグメントのメンテナンスが随分と簡
単になった。しかし、8iまでOracleの運用管理をしていた方は、INSERTや
UPDATEを行っている時に以下のようなロールバックセグメントが足りないエ
ラーを一度は経験しているであろう。

ORA-01628:最大エクステントに達しました。

しかも、INSERT処理でもこのようなエラーに出くわす時がある。INSERTでは
、更新前の情報(ロールバックするべき情報)が必要ではないにも関わらず
である。

そこで、実際に3万件のINSERTを行って作成されるUNDOブロック数を見ると
4MBものサイズのデータが作られていた。

*************************************************************
□3万件のINSERT後にv$transaction 表より作成されたUNDO情報を確認

SQL> insert into temp_work select * from temp

SQL> select USED_UBLK from v$transaction;

 USED_UBLK
----------
      1158

1158ブロック × 2KB(oracleのブロックサイズ) = 約2MB!!

ご存知の方も多いと思いますが、実はこれはインデックスの情報がほとんど
なのである。実際にインデックスを削除した後に同様のINSERTを行ったとこ
ろ、驚くべきことに、作成されるUNDO情報のデータ量が 1/10 になった。

*************************************************************
□インデックスの削除後に3万件のINSERT後にv$transaction 表より作成され
たUNDO情報を確認

 USED_UBLK
----------
       102

102ブロック × 2KB(oracleのブロックサイズ) = 約200KB!!

1つのインデックスだけでこれだけの差が出るということは、複数のインデッ
クスがあった場合のUNDO情報がいかばかりであるか想像に難くない。

これだけUNDO情報が大きくなる原因は、インデックスの場合は、更新前の値
だけではなく、更新後の値のUNDOエントリも作成される為である。

インデックスがない場合は、更新後のUNDOエントリは作成されないので、UNDO
の情報が少ないのである。

ちなみに、ここで1つだけ注意する点がある。上記のINSERT文の場合はSELECT
の結果を一括でTEMPテーブルにINSERTしている。しかし、これを以下の例の
ように、LOOP処理などを使用して、1行ずつのINSERT処理を行なうと、1レコ
ードに対して1UNDOエントリが作成され、結果として大量のUNDOエントリが作
成されるのである。

*************************************************************
□おなじみ弊社開発言語POPSQLによるLOOPでのインサート

CONNECT scott/tiger                        ←Oracleに接続
SAMPLE SELECT ID FROM TEMP2;               ←カーソルをオープン

LOOP(X=0;X<SEL_CNT;X++)                  ←フェッチされた行数LOOP

    SQL insert into temp values(ID[X]);  ←INSERT文

ENDLOOP

次回からはいよいよRAC環境のみで発生するSCUR(共有カレント・ブロック)
、PI(Past Image)のステータスに関しての検証を行っていく。CRブロック
に関する基本的な動きが理解できていれば問題なく検証が進んで行くものと
思っているのだが。。。少し不安である。

以上、茅ヶ崎にて