ロールバックセグメントに関する検証 その5

~ロールバックセグメントに関する検証 その5 ~
ペンネーム ちゃむ

前回は、2.TRANSACTIONS_PER_ROLLBACK_SEGMENTで指定した数だけ、各ロール
バック・セグメントで同時トランザクションを処理できるのかどうかに関して
の検証を行った。

今回は、前回のエラーの内容
「ORA-1554 トランザクション表にトランザクション・スロットがありません。」
に関して迫ってみる。
(以下の検証は、NT版 Oracle8.1.6 DB_BLOCK_SIZE=2Kの環境で行なった)

そもそも、トランザクション表とは何のことなのだろうか?

トランザクション表は、ロールバック・セグメントのセグメント・ヘッダーの
中に存在している。そこに、トランザクション情報を確保している。例えば、
UPDATE文などの更新処理が行われる際、更新前情報をロールバック・セグメント
に格納するが、まず始めにトランザクション表を更新する。

では、実際にトランザクション表を見てみよう。

前回、rbs_find50というロールバック・セグメントに、21個の同時トランザク
ションをエントリさせたが、その時の様子をブロック・ダンプで見てみよう。

セグメント・ヘッダーに存在するのだから、DBA_SEGMENTSのHEADER_FILE列と、
HEADER_BLOCK列で場所を確認できる。

SQL> col SEGMENT_NAME format a15
SQL> SELECT SEGMENT_NAME , HEADER_FILE , HEADER_BLOCK FROM DBA_SEGMENTS
     WHERE SEGMENT_NAME = 'RB_FIND50' ;

SEGMENT_NAME    HEADER_FILE HEADER_BLOCK
--------------- ----------- ------------
RB_FIND50                16          537

この情報を元にブロック・ダンプを取得する。これは、同時トランザクション
が発生している最中に取得したものである。
(初期化パラメータuser_dump_destで指定された場所に出力される)

ALTER SYSTEM DUMP DATAFILE 16 BLOCK 537 ;

以下はトランザクション表(TRN TBL)を抜粋したもの

TRN TBL

index  state cflags  wrap#    uel         scn            dba            parent-xid    nub
------------------------------------------------------------------------------------------------
 0x00   10    0xc0  0x0023  0x0000  0x0000.00ebcf59  0x0400021e  0x0000.000.00000000  0x00000001
 0x01   10    0xc0  0x0023  0x0000  0x0000.00ebcf5a  0x0400021e  0x0000.000.00000000  0x00000001
 0x02   10    0xc0  0x0023  0x0000  0x0000.00ebcf5a  0x0400021d  0x0000.000.00000000  0x00000001
 0x03   10    0xc0  0x0023  0x0000  0x0000.00ebcf5a  0x0400021c  0x0000.000.00000000  0x00000001
 0x04   10    0xc0  0x0023  0x0000  0x0000.00ebcf5a  0x0400021f  0x0000.000.00000000  0x00000001
 0x05   10    0xc0  0x0023  0x0000  0x0000.00ebcf5a  0x04000220  0x0000.000.00000000  0x00000001
 0x06   10    0xc0  0x0023  0x0000  0x0000.00ebcf5a  0x04000221  0x0000.000.00000000  0x00000001
 0x07   10    0xc0  0x0023  0x0000  0x0000.00ebcf5a  0x04000223  0x0000.000.00000000  0x00000001
 0x08   10    0xc0  0x0023  0x0000  0x0000.00ebcf5a  0x04000222  0x0000.000.00000000  0x00000001
 0x09   10    0xc0  0x0023  0x0000  0x0000.00ebcf5d  0x04000224  0x0000.000.00000000  0x00000001
 0x0a   10    0xc0  0x0022  0x0001  0x0000.00ebcf57  0x00800229  0x0000.000.00000000  0x00000001
 0x0b   10    0xc0  0x0022  0x0001  0x0000.00ebcf58  0x0080022c  0x0000.000.00000000  0x00000001
 0x0c   10    0xc0  0x0022  0x0001  0x0000.00ebcf59  0x0080022d  0x0000.000.00000000  0x00000001
 0x0d   10    0xc0  0x0022  0x0001  0x0000.00ebcf57  0x00800228  0x0000.000.00000000  0x00000001
 0x0e   10    0xc0  0x0022  0x0001  0x0000.00ebcf57  0x0080022a  0x0000.000.00000000  0x00000001
 0x0f   10    0xc0  0x0022  0x0001  0x0000.00ebcf59  0x0080022e  0x0000.000.00000000  0x00000001
 0x10   10    0xc0  0x0022  0x0000  0x0000.00ebcf59  0x0400021a  0x0000.000.00000000  0x00000001
 0x11   10    0xc0  0x0022  0x0001  0x0000.00ebcf57  0x0080022b  0x0000.000.00000000  0x00000001
 0x12   10    0xc0  0x0022  0x0001  0x0000.00ebcf59  0x00800231  0x0000.000.00000000  0x00000001
 0x13   10    0xc0  0x0022  0x0001  0x0000.00ebcf59  0x00800230  0x0000.000.00000000  0x00000001
 0x14   10    0xc0  0x0022  0x0001  0x0000.00ebcf59  0x0080022f  0x0000.000.00000000  0x00000001

まず、この行数を数えてほしい。21行というのが確認できるはずである。この
21行のトランザクション表のデータ数は、1つのロールバック・セグメントで扱
える同時トランザクション数と一致する。
つまりは、TRANSACTIONS_PER_ROLLBACK_SEGMENTがMAXで21までしか設定できな
い原因と言えないだろうか?

以下に、各項目の意味を示す。

index      → v$transactionのXIDSLOT列に一致(スロット番号)
state      → トランザクションがアクティブのときに9から10に変わる
wrap#      → v$transactionのXIDSQN列に一致(順序番号)
cflags     → そのスロットが使用された後、0x00から0xc0に変わるが詳しいことはわからない
uel        → これに関しても詳しいことはわからない
scn        → SCN(System Change Number)システム変更番号
dba        → undoブロックのdba(data block address)を示す
parent-xid → パラレルDMLのときに使用される親トランザクション番号
              パラレルDMLを使用しないときは、0x0000.000.00000000が格納される
nub        → v$transactionのUSED_UBLK列に一致
              (使用されたロールバック・セグメントのブロック数)

最後に、dbaがロールバック・セグメントのdba、つまりudaであることを証明す
るSQL文を実行してみよう。

上記のトランザクション表中の1行目の16進数のdbaである「0x0400021e」を、
10進数に変換すると67109406となる。これを用いて以下のSQL文を実行すると、
ロールバック・セグメントのdbaということがわかる。

SELECT SEGMENT_NAME,SEGMENT_TYPE FROM DBA_EXTENTS
WHERE FILE_ID= DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(67109406)
AND DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(67109406) BETWEEN
BLOCK_ID AND BLOCK_ID+BLOCKS ;

SEGMENT_NAME   SEGMENT_TYPE
-----------------------------
RB_FIND50      ROLLBACK

ちなみに、DATA_BLOCK_ADDRESS_FILE、DATA_BLOCK_ADDRESS_BLOCKはそれぞれ、
dbaからファイル番号とブロック番号を求めるためのファンクションである。

以上 養命酒は、結構アルコール濃度 高いのね 茅ヶ崎にて