ログマイナー再び!! その4
<ログマイナー再び!! その4>
ペンネーム: ぽっちゃりメタボン
こんにちは!!、ぽっちゃりメタボンです。
めっきり茅ヶ崎も寒くなってきましたが、今週もはりきって検証しちゃうぞー。
▼ 前回のおさらい
前回は LogMiner ディクショナリとして抽出されたREDOログをダンプから確認
し、ログマイナー関連の表に対するDMLが実行されていることを確認しました。
気になるのはどういったSQL文がdbms_logmnr_d.build プロシージャ実行時
に流れているのかですが、今回は SQL Trace を使用して、確認します。
▼ 環境のおさらい
OS:Red Hat Enterprise Linux ES release 3
DB:10gR2(10.2.0.1)
▼ SQL Trace を取得
1. セッション単位で SQL Trace を有効にします。
SQL> alter session set sql_trace=true; セッションが変更されました。
2. ディクショナリをアーカイブREDOログへ抽出します。
SQL> execute dbms_logmnr_d.build(options=> - dbms_logmnr_d.store_in_redo_logs); PL/SQLプロシージャが正常に完了しました。
トレースファイルが初期化パラメータ user_dump_dest へ出力されているの
で早速、確認してみましょう。
さて、どのようなSQL文が実行されているのでしょうか。
▼ トレースを眺めてみるのだ!!
トレースファイルからSQL文のみを抽出します。
$ egrep -v "^*|^XCTEND|^EXEC #|^PARS|^FETCH|^STAT|^END|^=" ora102_ora_1712.trc>/home/ora102/sql.txt
抽出した内容をシーケンシャルにまとめたものが以下となります。
トレースファイルより抜粋———————————————
1. ディクショナリのロック
LOCK TABLE SYS.OBJ$, SYS.TAB$, SYS.COL$, SYS.ATTRCOL$, SYS.TS$,
SYS.IND$, SYS.USER$, SYS.TABPART$, SYS.TABSUBPART$,
SYS.TABCOMPART$, SYS.TYPE$, SYS.COLTYPE$, SYS.ATTRIBUTE$,
SYS.LOB$, SYS.CDEF$, SYS.CCOL$, SYS.ICOL$, SYS.LOBFRAG$,
SYS.INDPART$, SYS.INDSUBPART$, SYS.INDCOMPART$
IN SHARE MODE NOWAIT
2. カレントREDOログの変更
ALTER SYSTEM SWITCH ALL LOGFILE
3. LogMiner ディクショナリ のビルドログへINSERT
(CURRENT_BUILD_STATE = 1)
INSERT INTO SYS.LOGMNR_BUILDLOG
4. ログマイナー実行時に必要となる情報を収集し、INSERT
※()内はinsert情報収集元となります。
INSERT INTO LOGMNRG_SEED$
(SYS.OBJ$,SYS.TAB$,SYS.COL$,SYS.USER$)
INSERT INTO SYS.LOGMNRG_DICTIONARY$
(SYS.OBJ$,SYS.V$DATABASE,SYS.NLS_DATABASE_PARAMETERS,
SYS.X$KCCRT,V$INSTANCE)
INSERT INTO SYS.LOGMNRG_OBJ$ (SYS.OBJ$)
INSERT INTO SYS.LOGMNRG_TAB$ (SYS.TAB$$)
INSERT INTO SYS.LOGMNRG_COL$ (SYS.COL$)
INSERT INTO SYS.LOGMNRG_ATTRCOL$ (SYS.ATTRCOL$)
INSERT INTO SYS.LOGMNRG_TS$ (SYS.TS$)
INSERT INTO SYS.LOGMNRG_IND$ (SYS.IND$)
INSERT INTO SYS.LOGMNRG_USER$ (SYS.USER$)
INSERT INTO SYS.LOGMNRG_TABPART$ (SYS.TABPART$)
INSERT INTO SYS.LOGMNRG_TABSUBPART$ (SYS.TABSUBPART$)
INSERT INTO SYS.LOGMNRG_TABCOMPART$ (SYS.TABCOMPART$)
INSERT INTO SYS.LOGMNRG_TYPE$ (SYS.TYPE$)
INSERT INTO SYS.LOGMNRG_COLTYPE$ (SYS.COLTYPE$)
INSERT INTO SYS.LOGMNRG_ATTRIBUTE$ (SYS.ATTRIBUTE$)
INSERT INTO SYS.LOGMNRG_LOB$ (SYS.LOB$)
INSERT INTO SYS.LOGMNRG_CDEF$ (SYS.CDEF$)
INSERT INTO SYS.LOGMNRG_CCOL$ (SYS.CCOL$)
INSERT INTO SYS.LOGMNRG_ICOL$ (SYS.ICOL$)
INSERT INTO SYS.LOGMNRG_LOBFRAG$ (SYS.LOBFRAG$)
INSERT INTO SYS.LOGMNRG_INDPART$ (SYS.INDPART$)
INSERT INTO SYS.LOGMNRG_INDSUBPART$ (SYS.INDSUBPART$)
INSERT INTO SYS.LOGMNRG_INDCOMPART$ (SYS.INDCOMPART$)
5. 収集した情報をTRUNCATE
TRUNCATE TABLE SYS.LOGMNRG_ATTRCOL$
TRUNCATE TABLE SYS.LOGMNRG_ATTRIBUTE$
TRUNCATE TABLE SYS.LOGMNRG_CCOL$
TRUNCATE TABLE SYS.LOGMNRG_CDEF$
TRUNCATE TABLE SYS.LOGMNRG_COL$
TRUNCATE TABLE SYS.LOGMNRG_COLTYPE$
TRUNCATE TABLE SYS.LOGMNRG_ICOL$
TRUNCATE TABLE SYS.LOGMNRG_IND$
TRUNCATE TABLE SYS.LOGMNRG_INDCOMPART$
TRUNCATE TABLE SYS.LOGMNRG_INDPART$
TRUNCATE TABLE SYS.LOGMNRG_INDSUBPART$
TRUNCATE TABLE SYS.LOGMNRG_LOB$
TRUNCATE TABLE SYS.LOGMNRG_LOBFRAG$
TRUNCATE TABLE SYS.LOGMNRG_OBJ$
TRUNCATE TABLE SYS.LOGMNRG_SEED$
TRUNCATE TABLE SYS.LOGMNRG_TAB$
TRUNCATE TABLE SYS.LOGMNRG_TABCOMPART$
TRUNCATE TABLE SYS.LOGMNRG_TABPART$
TRUNCATE TABLE SYS.LOGMNRG_TABSUBPART$
TRUNCATE TABLE SYS.LOGMNRG_TS$
TRUNCATE TABLE SYS.LOGMNRG_TYPE$
TRUNCATE TABLE SYS.LOGMNRG_USER$
6. ビルドログのUPDATE (CURRENT_BUILD_STATE = 0)
UPDATE SYS.LOGMNR_BUILDLOG
7. REDOログをアーカイブへ出力
ALTER SYSTEM ARCHIVE LOG CURRENT
抜粋—————————————————————–
メタボン(独り言・・・)>
ほうほう、こうなっているのねー。なるほど、なるほど。
以下に考察を述べます。
▼ 考察
1.)
マニュアルには「ディクショナリをREDO ログ・ストリームに抽出している
間は、DDL 文を実行できません。したがって、REDO ログ・ファイルに抽
出されるディクショナリは、一貫性が保証されます」とあります。
これは「1.ディクショナリのロック」を行い、実現している事が確認でき
ます。
先にロックが掛っていたらどうなる? ======================
他のセッションから先にディクショナリにロックをかけてから
dbms_logmnr_d.build(options=>dbms_logmnr_d.store_in_redo_logs)を
実行すると、最大600回(600秒) までロックの獲得を再試行するようです。
その後、以下のエラーが発生して実行に失敗します。
ORA-01327: ビルドに必須のシステム・ディクショナリの排他ロックに
失敗しました。
==========================================================
2.)
「2.カレントREDOログの変更」で1個、ディクショナリ情報で最低1個以
上(LogMiner ディクショナリは複数アーカイブログへ跨ることもあるため)
アーカイブログは最低2個以上出力されることが分かります。
3.)
INSERTしたデータを全てTRUNCATEしています。
よって、データを保持するためではなく更新を行うことによってREDOへの書
き込みを発生させるためだけにINSERT処理をしていると考えられます。
結果、ディクショナリ情報はアーカイブREDOログへ出力されることになりま
す。
4.)
ビルドログは以下ような構造になっています。
SQL> desc LOGMNR_BUILDLOG 名前 NULL? 型 ----------------------------------------- -------- ------------ INITIAL_XID NOT NULL VARCHAR2(22) BUILD_DATE VARCHAR2(20) DB_TXN_SCNBAS NUMBER DB_TXN_SCNWRP NUMBER CURRENT_BUILD_STATE NUMBER COMPLETION_STATUS NUMBER MARKED_LOG_FILE_LOW_SCN NUMBER
作成日(BUILD_DATE)、実行状態(COMPLETION_STATUS 0=作成中、1=完了)等を
確認できます。
dbms_logmnr_d.build(options=>dbms_logmnr_d.store_in_redo_logs) 実行毎
に1レコード生成されるため、履歴管理の役割を持っています。
ディクショナリオプションである「REDOログへのディクショナリ抽出」に
フォーカスを当てての検証を行いましたが、如何でしたでしょうか?
内部構造を抑えた上で、運用を行えば問題発生時に対処しやすくなるのでは
ないでしょうか。
次回は、ログマイナー事前準備として、おまじないのように行った
「サプリメンタルロギング」について取り上げる予定です。
今回はここまで!!
人肌が恋しい 茅ヶ崎より