続 X$BH に関する検証 その6
<続 X$BH に関する検証 ~その6~>
ペンネーム ちょびひげ
前回までは「単一サーバ」で、UPDATEなどの各処理を行い、どのような処理
を行なった場合に、CRブロックが作成される状況を見てきた。CRブロックは
読取一貫性を保つ為に作成されるブロックである。つまり、アクセスするデ
ータのバージョン(SCN)が欲しいバージョンと異なる場合(SCNの番号が必
要なSCNより大きい)にCRブロックが作成される。
CRブロックを作成するにはUNDOブロックを使用して、ブロックのバージョンを
古くする必要がある。ここで使用するUNDOブロックを特定するには、ブロッ
ク内のトランザクション・エントリが必要となる。
トランザクション・エントリに関しては、今までにも<ロックに関する検証
>や<ロールバックセグメントに関する検証>などで部分的に触れてきたが、
今回はバッファのダンプを取得して簡単にトランザクション・エントリとロ
ックの関係を見ていく。次回、カレント・ブロックとUNDO情報を使用して、
CRブロックが作成される様子を見ていく。
とりあえずは、ロックのメカニズムをおさらいしたい。
今回の検証も前回と同様に以下環境で行う。
*************************************************************
◆環境
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
まず初めに、2行のUPDATEをおこなって、どのようにロックが取得されている
かを見てみる。
SQL> update test set id1=1 where id1>1; 2行が更新されました。 OBJECT_NAME STATE DBABLK BA -------------------- ----- ---------- -------- TEST xcur 70913 54D12000 ← セグメント・ヘッダ TEST xcur 70914 54D0E000 ← データ・ブロック TEST_IDX xcur 96394 54D10000 ← インデックス
データが以下の様に更新されている ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ID1 ID2 TEXT ---------- ---------- -------------------- 1 1 insight 1 2 insight 1 3 insight
◇バッファ・ダンプを出力する為に、以下のコマンドを実行
SQL> alter session set events 'immediate trace name buffers level 6';
では、ダンプを見てみよう。
各ブロックのバッファ・ダンプは以下の構成である。
【バッファ・ヘッダ部】
・
【ブロック・ヘッダ部】
・
【データ・ブロック部】
・
・
上記の各部分に関して簡単に説明していく。
【バッファ・ヘッダ部】
バッファ・ヘッダにはバッファ・アドレス(BA)が含まれており、これを元
にX$BH表のデータとの結び付けを行う。また、この部分にSCN番号をもってお
り、現在のブロックのバージョンを知ることができる。
バッファ・ヘッダに関しては<Oracle 9iに関する検証>で既に行っているの
で詳しくは紹介しない。
【ブロック・ヘッダ部】
以下は、バッファ・ダンプのブロック・ヘッダの一部分である。
*************************************************************
ブロック・ヘッダ(テーブル)
Block header dump: 0x00411502 Object id on Block? Y seg/obj: 0x82d0 csc: 0x00.887cc20 itc: 2 flg: O typ: 1 - DATA fsl: 0 fnx: 0x0 ver: 0x01 Itl Xid Uba Flag Lck Scn/Fsc 0x01 0x0008.028.00027e99 0x00800974.09bd.3b C--- 0 scn 0x0000.08877c26 0x02 0x0002.02d.000281f5 0x0080083b.08ee.28 ---- 2 fsc 0x0000.00000000 ↑ ↑ Itlエントリ番号 ロックの行数
【Itl, Lck】
0x02 のトランザクション・エントリ(Itl)がロック(Lck)を2行取得して
いる様子が分かる。フラグ(Flag)がCのエントリを既にコミットされたこ
とを示している。トランザクション・エントリはロールバックの情報と結び
つく重要な情報であるが、これに関しては次回詳しく見ていく予定である。
今回は上記のトランザクション・エントリとブロック内の各レコードの関係
を見て頂きたい。Itlが0x02のトランザクションが、ロックを2行取得してい
るが、どうやってレコードと結び付けているのであろうか?この結び付けが
出来なければ行ロックを実現することは出来ない。
では、データ・ブロックの内容を見てみる事にする。
【データ・ブロック部】
*************************************************************
データ・ブロック(テーブル)
data_block_dump,data header at 0x54d5405c =============== ・ <<省略>> ・ 0x16:pri[2] offs=0x1f6d block_row_dump: ↓【注目!】 tab 0, row 0, @0x1f8f tl: 17 fb: --H-FL-- lb: 0x0 cc: 3 col 0: [ 2] c1 02 ← ID1 = 1 col 1: [ 2] c1 02 ← ID2 = 1 col 2: [ 7] 69 6e 73 69 67 68 74 ← TEXT= insight tab 0, row 1, @0x1f5c tl: 17 fb: --H-FL-- lb: 0x2 cc: 3 col 0: [ 2] c1 02 ↑【注目!】 col 1: [ 2] c1 03 ← ID2 = 2 col 2: [ 7] 69 6e 73 69 67 68 74 tab 0, row 2, @0x1f6d tl: 17 fb: --H-FL-- lb: 0x2 cc: 3 col 0: [ 2] c1 02 ↑【注目!】 col 1: [ 2] c1 04 ← ID2 = 3 col 2: [ 7] 69 6e 73 69 67 68 74 end_of_block_dump
上記のデータを見ていただくとロックが掛かっていない行のlbは0x0であるが
、ロックが掛かっている行には、lb に先程のItlエントリ番号(0x02)がは
いっているのが確認できる。
このように、行単位でロックを取得し、そのロックを保持しているトランザ
クションの特定を行う事が出来るわけである。
では、インデックスの方も簡単にみてみよう。
*************************************************************
ブロック・ヘッダ(インデックス)
Block header dump: 0x0041788a Object id on Block? Y seg/obj: 0x82cf csc: 0x00.888c646 itc: 3 flg: - typ: 2 - INDEX fsl: 0 fnx: 0x0 ver: 0x01 Itl Xid Uba Flag Lck Scn/Fsc 0x01 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000 0x02 0x0008.028.00027e99 0x00800974.09bd.3c C--- 0 scn 0x0000.08877c26 0x03 0x0002.02d.000281f5 0x0080083b.08ee.2a ---- 4 fsc 0x001c.00000000 ↑ ロックを4つ取得!
データ・ブロック(インデックス)
Leaf block dump =============== ・ <<省略>> ・ row#0[7996] flag: -----, lock: 0 col 0; len 2; (2): c1 02 ← ID1 = 1 col 1; len 6; (6): 00 41 15 02 00 00 ← ROWID row#1[7912] flag: -----, lock: 3 ← Itl 3 がロックを取得 col 0; len 2; (2): c1 02 col 1; len 6; (6): 00 41 15 02 00 01 row#2[7924] flag: -----, lock: 3 col 0; len 2; (2): c1 02 col 1; len 6; (6): 00 41 15 02 00 02 row#3[7984] flag: ---D-, lock: 3 ← 更新前情報には削除フラグ(D) col 0; len 2; (2): c1 03 ← ID1 = 2 col 1; len 6; (6): 00 41 15 02 00 01 row#4[7972] flag: ---D-, lock: 3 ← 更新前情報には削除フラグ(D) col 0; len 2; (2): c1 04 ← ID1 = 3 col 1; len 6; (6): 00 41 15 02 00 02 ----- end of leaf block dump -----
インデックスには更新前の情報も格納されているので、計4つのロックを保持
している。各更新前のレコードがどの更新後のレコードに相当するかはROWID
から確認することが出来る。上記の例では “col 1” の “00 41 15 02 00 01”
がROWIDを示している。
今回はトランザクション・エントリとロックされた各レコードとの関係をみ
た。トランザクション・エントリがOracleの行ロックを可能にしている重要
な情報であることが分かる。次回はトランザクション・エントリとUNDO情報
との関係を見ていく。
以上、雨上がりの茅ヶ崎にて