続 X$BH に関する検証 その7
<続 X$BH に関する検証 ~その7~>
ペンネーム ちょびひげ
前回はOracleのブロック内でトランザクション・エントリと各データとの関
係を見ることによって行単位のロックがどのように取得されるのかを見た。
今回は、ロックは一旦忘れて、トランザクション・エントリとUNDO情報の関
連を見ていく。
あるユーザがUPDATEを行うとする。更新対象のブロックに対して、すでに他
のセッションから更新が行われていたらどうするか?アクセスするデータの
バージョン(SCN)が欲しいバージョンと異なる(SCNの番号が必要なSCNより
大きい)ので、読取一貫性を保証する為に、CRブロックが作成する。当然、
CRブロックの作成には、UNDO情報が必要となるのでトランザクション・エン
トリから必要なUNDO情報を取得する。
では、どのようにトランザクション・エントリからUNDO情報を取得している
のか?
今回も以下の環境で検証を進める。
*************************************************************
◆環境
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
今回の検証は以下の順番で進めていく。
(1)UPDATE処理を行ったブロックをX$BH表より確認 (2)更新ブロックのトランザクション・エントリ(Itl)から、該当するUNDO 情報を保持しているブロックのアドレス(Uba)を確認 (3)ロールバック情報のダンプを取得してUNDOエントリを確認
まずは2行のUPDATE処理を行ってどのようなロールバック情報が作成されるの
かを見ていく。
以下が更新されたブロックのバッファ・ダンプのブロック・ヘッダ部である。
Block header dump: 0x00411502 Object id on Block? Y seg/obj: 0x82da csc: 0x00.8921cd5 itc: 2 flg: O typ: 1 - DATA fsl: 0 fnx: 0x0 ver: 0x01 ↓【Wrap】 Itl Xid Uba Flag Lck Scn/Fsc 0x01 0x0007.01c.00027fa1 0x00800a8d.0998.0f C-U- 0 scn 0x0000.0892196f 0x02 0x0007.00d.00027faa 0x00800a94.0998.59 ---- 2 fsc 0x0000.00000000 ↑【スロット番号】 ↑最後のUNDOレコード番号(16進) ↑【ロールバック番号】 ↑UNDOブロックのDBA(16進)
更新を行ったトランザクションのエントリ番号は0x02である。Uba(Undo Block
Address)は最後のUNDOエントリのアドレスを示している。
Uba : 0x00800a8d.0998.0f
左から最後のUNDOエントリの【DBA】【シーケンス】【レコード番号】を表し
ている。全て16進数なので、10進数に変換したのが以下の番号である。
ファイル番号 : 2 ブロック番号 : 2708 レコード番号(最後): 89
では上記のレコードのデータベース・バッファ上での状態をX$BH表より
検索して見てみる。
*************************************************************
【データベース・バッファ上の各オブジェクトの状態】
OBJ OBJECT_NAME STATE DBARFIL DBABLK BA ---------- -------------------- ----- ---------- ---------- -------- 4294967295 xcur 2 2708 550CE000 33498 TEST xcur 1 70913 551E8000 33498 TEST xcur 1 70914 551EC000 33497 TEST_IDX xcur 1 96394 551EA000
ファイル番号(DBARFIL)が2でブロック番号が2708のオブジェクトを見ると
オブジェクト番号(OBJ)が4294967295となっている。この番号はロールバッ
ク・セグメントを表す番号である。
このブロック(ロールバック・セグメント)のバッファ・ダンプを取得して
実際に見てみると、以下の構成になっている。
【バッファ・ヘッダ部】
・・
・・
【データ・ブロック部】
◇UNDOエントリ・マップ
◇UNDOエントリ
UNDOエントリ・マップはUNDOブロック内にあるレコードの索引のようなもの
である。では、先程調べた情報から89番目のレコード見てみよう。89は16進
数にすると59である。
*************************************************************
【UNDOエントリ58番(16進数)】
↓ *----------------------------- * Rec #0x58 slt: 0x0d objn: 33468(0x000082bc) objd: 33498 tblspc: 0(0x00000000) * Layer: 11 (Row) opc: 1 rci 0x00 ←【※注目1※】 Undo type: Regular undo Begin trans Last buffer split: No Temp Object: No Tablespace Undo: No rdba: 0x00000000 *----------------------------- uba: 0x00800a94.0998.57 ctl max scn: 0x0000.0892196f prv tx scn: 0x0000.0892197e KDO undo record: KTB Redo op: 0x03 ver: 0x01 op: Z KDO Op code: URP row dependencies Disabled xtype: XA bdba: 0x00411502 hdba: 0x00411501 itli: 2 ispac: 0 maxfr: 4863 tabn: 0 slot: 1(0x1) flag: 0x2c lock: 0 ckix: 1 ncol: 3 nnew: 1 size: 0 col 0: [ 2] c1 03 ←【ID1 = 2 (更新前情報)】 ↓【UNDOエントリ59番(16進数)】 *----------------------------- * Rec #0x59 slt: 0x0d objn: 33468(0x000082bc) objd: 33498 tblspc: 0(0x00000000) * Layer: 11 (Row) opc: 1 rci 0x58 ←【※注目2※】 Undo type: Regular undo Last buffer split: No Temp Object: No ↑ Tablespace Undo: No 【最後のUNDOエントリを表す】 rdba: 0x00000000 *----------------------------- KDO undo record: KTB Redo op: 0x02 ver: 0x01 op: C uba: 0x00800a94.0998.58 KDO Op code: URP row dependencies Disabled xtype: XA bdba: 0x00411502 hdba: 0x00411501 itli: 2 ispac: 0 maxfr: 4863 tabn: 0 slot: 2(0x2) flag: 0x2c lock: 0 ckix: 64 ncol: 3 nnew: 1 size: 0 col 0: [ 2] c1 04 ←【ID1 = 2 (更新前情報)】
よーく見ても分かりづらいので、簡単にまとめると以下のような内容である。
************************************************************* Rec #0x58 slt: 0x0d rci 0x00[UNDOエントリ58番(16進数)] ↑ Rec #0x59 slt: 0x0d rci 0x58[UNDOエントリ59番(16進数)] *************************************************************
最後のUNDOエントリ(Rec #0x59)から元の状態に戻し始めて、rci が指す前
のUNDOエントリを適用していく。一番前のUNDOエントリ(Rec #0x58)まで来
ると、前を指すrci がないためにCRブロックの作成が終了すると考えられる。
実際は以下の様にインデックスのUNDOエントリも続けて入っている
************************************************************* Rec #0x5a slt: 0x0d rci 0x59[UNDOエントリ59番(16進数)] index undo for leaf key operations ↑ Rec #0x5b slt: 0x0d rci 0x5a[UNDOエントリ59番(16進数)] index undo for leaf key operations *************************************************************
つまり、ビデオテープの巻き戻しのように、UNDOエントリを当てつつ、ブロ
ックを過去のバージョンに戻していっているわけである。CRブロックが作成
されるイメージを持って頂けたであろうか?
ちなみ、過去の検証(その5)では、全件検索でのUPDATE、SELECTではCRが
作成されないことから、インデックスを使用しない場合はインデックスのCR
ブロックまでは作成されないような仕組みになっていると考えられる。
CRブロックが作成されるケース(複数セッション) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SELECT UPDATE INSERT ------------------------ ------- ------- ------- 全件検索 - TABLE ○ ○ ― - INDEX × × ― インデックス検索 - TABLE ○ × ― - INDEX ○ ○ ―
以上、秋晴れの茅ヶ崎にて