トランザクションエントリに関する検証 その3
<トランザクションエントリに関する検証 その3>
ペンネーム しゅらん
今週も引き続きテーブルやインデックスを作成する際に設定するinitrans、
maxtransについて検証をしたいと思います。
検証環境
OS:Windows2000 Server
Oracle:8.1.7
DB_BLOCK_SIZE:8K
—maxtransに関する検証 ブロック格納率—
tbl_shu1,tbl_shu2の定義
ID DATE TEXT CHAR(10)
前回はmaxtransを1 に設定して、200同時sessionにてインサートを行うとどう
なるかの検証をしました。
select TABLE_NAME,NUM_ROWS,BLOCKS from dba_tables where table_name='TBL_SHU1'; TABLE_NAME NUM_ROWS BLOCKS ------------------------------ ---------- ---------- TBL_SHU1 200000 148989
上記のように1ブロックに2レコードも格納されていない結果となった。
また、3つのsessionから同時にinsertを行い、結果を確認するとやはり3つの
ブロックを使用していた。
select TABLE_NAME,NUM_ROWS,BLOCKS from dba_tables where table_name='TBL_SHU2'; TABLE_NAME NUM_ROWS BLOCKS ------------------------------ ---------- ---------- TBL_SHU2 3 3
このことから、ブロック内のトランザクションエントリがmaxtransの値に達す
ると、Oracleは次のトランザクションを待たせないために、ハイウォーターマ
ークを引き上げ、新しいブロックを割り当てている事が分かった。
今回はブロック内の残ったスペース、フリーリスト(次のレコードの挿入先)
について検証を行います。
—ダンプファイル—
フリーリストやハイウォーターの情報はセグメントヘッダーで管理しているの
でセグメントヘッダーのダンプを取って、確認をしてみましょう。
SQL> select file_id,block_id from dba_extents where segment_name = 'TBL_SHU2' and extent_id=0; FILE_ID BLOCK_ID ---------- ---------- 7 2 SQL> alter system dump datafile 7 block 2; システムが変更されました。
(注)このコマンドはoracleのinternalなコマンドでサポートの対象外にもなっ
ているので、使用する際にはご注意下さい。
(dumpより抜粋)
?buffer tsn: 6 rdba: 0x01c00002 (7/2) ?Highwater:: 0x01c00006 ext#: 0 blk#: 3 ext size: 2559 ?SEG LST:: flg: USED lhd: 0x01c00005 ltl: 0x01c00005
?のrdbaはこのブロックのデータブロックアドレス(以下DBA)
?のHighwaterはハイウォーターマークのDBA(ハイウォーターはデータが入っ
ている最後のブロックの1個先を示している)
?のlhdはフリーリストの最初の空きブロックのDBA
つまり現在のブロックの状況は以下のようになっている。
0x01c00002 segment header 0x01c00003 datablock 1 0x01c00004 datablock 2 0x01c00005 datablock 3 0x01c00006 highwater の指すブロック
?のlhdはdatablock 3 を指し示しているため、次にinsertするときには
datablock 3 に実際のデータが格納されることになる。
またdatablockのdumpも見てみよう。
0x01c00003 seg/obj: 0xc67 csc: 0x00.3f226 itc: 1 flg: - typ: 1 - DATA 0x01c00004 seg/obj: 0xc67 csc: 0x00.3f227 itc: 1 flg: - typ: 1 - DATA 0x01c00005 seg/obj: 0xc67 csc: 0x00.3f228 itc: 1 flg: O typ: 1 - DATA
datablock1,2はflgが-(ハイフン)になっているが、datablock3はflgがOにな
っている。これもdatablock1,2がフリーリストから外れていることを示す。
これはつまり、3sessionで同時にinsertを行い、2つ目、3つ目ののsessionは
datablock1,2に対して挿入を行おうとしたが、トランザクションエントリを使
い切ったことにより、挿入が出来なかった。
これによりこのブロックは既に満杯という判断をoracleが下し、フリーリス
トから外れてしまったということであろう。
では実際にinsertを行ってみる。
(実行)insert into tbl_shu2 (TEXT) values ('PPPPPPPPPP');
再度ブロックダンプを取って、確認。
insert前
0x01c00005 nrow=1
insert後
0x01c00005 nrow=2
やはりdatablock3に格納された。
それではこのdatablock1,2は再利用されないのであろうか。
一度フリーリストから外れたブロックが再度フリーリストに組み込まれるには
対象のブロックに収まっているレコードのdeleteやupdateが行われ、その時点
でpctusedを下回った場合に再度フリーリストに組み込まれる。
SQL> delete from tbl_shu2 2 where to_char(id,'MM/DD HH24:MI:SS')='03/19 16:01:55'; 1行が削除されました。 SQL> commit; SQL> alter system dump datafile 7 block 3;
0x01c00003 seg/obj: 0xc67 csc: 0x00.443a3 itc: 1 flg: O typ: 1 - DATA
このように、flgがOに変わっていることが分かる。
そのため、insertしか行われないテーブルは再利用が行われず、無駄な領域だ
らけになってしまう。
次回も引き続きトランザクションエントリに関する検証を行います。
以上、桜の開花が待ち遠しい茅ヶ崎にて