HWエンキューでロックされているセグメントを特定する
はじめに
Oracleまわりのトラブルの調査のため、HWエンキューでロックされたセグメントを特定する方法を調べてみました。
環境
- Oracle 10g R2
HWエンキューってなんぞ?
Oracleのエンキューとは
エンキューは、データベース・リソースへのアクセスをシリアライズする共有メモリーの構造(ロック)です。
(Oracleエンキュー名)
です。
HWエンキューは、セグメントのHWM(High Water Mark; 最高水位標)を動かすときに行われるロックです。保持されているロック情報を示すV$LOCKビュー上では、TYPE='HW'のレコードとして表されます。
HWエンキューでロックしているセグメントを特定する
1. ロックされたHWエンキューが待っているデータのファイルとブロックを特定
まず、V$LOCKからTYPEが'HW'の行を探し、そのデータブロックアドレスのファイル番号とブロック番号を取得します。
HWエンキューの場合、V$LOCKのID1, ID2は下記のようになります。
- ID1: HWMが変更されるセグメントが格納されている表領域の番号
- ID2: セグメントヘッダの相対データブロックアドレス
(パフォーマンス・ビューを使用したインスタンスのチューニング - HWエンキュー)
また、ストアドファンクションDBMS_UTILITY.DATA_BLOCK_ADDRESS_FILEとDBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCKにデータブロックアドレスを渡して実行すると、そのデータブロックアドレスのファイル番号とブロック番号がわかります。
DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE
引数 dba にデータ・ブロック・アドレスを渡して実行すると、データ・ブロック・アドレスのファイル番号部分を返す
(DATA_BLOCK_ADDRESS_FILEファンクション - DBMS_UTILITY)DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE ( dba NUMBER) RETURN NUMBER;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK
引数 dba にデータ・ブロック・アドレスを渡して実行すると、データ・ブロック・アドレスのブロック番号部分を返す
(DATA_BLOCK_ADDRESS_BLOCKファンクション - DBMS_UTILITY)DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK ( dba NUMBER) RETURN NUMBER;
そこで、V$LOCKのID2をDATA_BLOCK_ADDRESS_FILEとDATA_BLOCK_ADDRESS_BLOCKに渡せばよさそうです。
SQLはこんな感じになります。
SELECT DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(ID2) "FILE_ID", DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(ID2) "BLOCK_ID" FROM V$LOCK WHERE TYPE = 'HW'
結果はこんな感じ。ファイル番号とブロック番号がわかりました。
FILE_ID | BLOCK_ID |
---|---|
20 | 29 |
2. ロックしているセグメントを特定
1.でわかったファイル番号とブロック番号から、HWエンキューでロックしているセグメントを特定します。
こんな感じのSQLを実行します。
SELECT OWNER, SEGMENT_NAME, SEGMENT_TYPE FROM DBA_EXTENTS WHERE FILE_ID = 20 AND 29 BETWEEN BLOCK_ID AND BLOCK_ID + BLOCKS - 1
WHEREの条件の値(上記の20と29)には、1.で調べたものを入れてください。
結果はこんな感じ。
OWNER | SEGMENT_NAME | SEGMENT_TYPE |
---|---|---|
ORACLE | SYS_LOB000001234C01234$$ | LOBSEGMENT |
どうやら SYS_LOB000001234C01234$$ というセグメントがロックされているらしい、ということがわかりました。
この情報をもとに原因を特定して、対策を行いましょう。
まとめ
HWエンキューでロックされているセグメントを特定する方法を調べてみました。
これでHWエンキューでずーっとロックされてエラいことになっても大丈夫ですね!