しばちょう先生の試して納得!DBAへの道 indexページ▶▶
残念ながら、本記事でご紹介しているData Recovery Advisorは、Oracle Database 23cで非サポートになってしまいました。それ以前のバージョンでは継続利用可能ですので、本記事は引き続き公開させて頂いておりますが、本機能の利用を検討される際には、ご利用中のデータベースのバージョンを必ずご確認ください。
みなさん、こんにちは。しばちょう”こと柴田長(しばた つかさ)です。気が付けば師走に突入し、忘年会のお誘いもチラホラと頂くようになってきましたね。今年も残り一ヶ月間、全力で走り抜けましょう。さて今回も、しつこいようですがRecovery Manager(RMAN)をご紹介していきます。

突然ですが、「確実に復旧できるバックアップを取得しておきたい」と言う要件がお客様から提示された場合、皆さんの回答はどんなものになりますでしょうか?様々な回答があると思いますが、私の回答は「壊れていないバックアップ」です。そして追加して、「障害を考慮したリカバリ手順」ですかね。バックアップを取得したから安心していてはいけません。万が一、障害が発生してデータベースのリカバリを実施しなければならなくなった場合に、そのバックアップ内のデータブロックが壊れていたらという可能性を考えると怖くなりますよね。また、データベースの障害はいつでも同じではありません。さまざまなタイプの障害がありますので、それらの障害に合わせて最適なリカバリ手順を実行するべきです。この辺りを全て網羅した設計書/手順書を作成するのは非常に難しいとも思います。
と言う事で、今回は「壊れていないバックアップ」を取得/検証するオペレーション、さらにはリカバリの達人並みに最適なリカバリ手順をアドバイスしてくれるData Recovery Advisorを体験して頂きたいと考えています。以下の演習をOracle Database 11g Release 2 Enterprise Editionのデータベースで試してみてください。
1. 次のSQLを実行し、RMANで非一貫性の高速増分バックアップを取得可能な設定として下さい。また、Flashback Loggingを有効化して下さい。
これらの設定が完了した後に、100MBの表領域”TBS24″をファイル・システム上に作成し、その表領域上に約64MBの表”TAB24″を作成して下さい。
$ sqlplus / as sysdba SQL> -- Version確認 select * from V$VERSION ; BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production PL/SQL Release 11.2.0.4.0 - Production CORE 11.2.0.4.0 Production TNS for Linux: Version 11.2.0.4.0 - Production NLSRTL Version 11.2.0.4.0 - Production SQL> -- InstanceのStatus確認 select STATUS from V$INSTANCE ; STATUS ------------ OPEN SQL> -- 高速リカバリ領域関連の初期化パラメータを設定 alter system set db_recovery_file_dest_size=10g scope=both sid='*' ; alter system set db_recovery_file_dest='+FRA' scope=both sid='*' ; show parameter db_recovery_file NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_recovery_file_dest string +FRA db_recovery_file_dest_size big integer 10G SQL> -- Archive Logモードへ変更 shutdown immediate; startup mount alter database archivelog; archive log list Database log mode Archive Mode Automatic archival Enabled Archive destination USE_DB_RECOVERY_FILE_DEST Oldest online log sequence 1 Next log sequence to archive 3 Current log sequence 3 SQL> -- Block Change Tracking Fileの有効化 alter database enable BLOCK CHANGE TRACKING using file '+FRA(CHANGETRACKING)' reuse ; select * from V$BLOCK_CHANGE_TRACKING ; STATUS FILENAME BYTES ---------- ------------------------------------------------ ---------- ENABLED +FRA/orcl/changetracking/ctf.291.832694657 11599872 SQL> -- Flashback Loggingの有効化 alter database flashback on ; select FLASHBACK_ON from V$DATABASE ; FLASHBACK_ON ------------------ YES SQL> -- Instanceをオープン状態へ alter database open ; select STATUS from V$INSTANCE ; STATUS ------------ OPEN
SQL> -- TBS24表領域と、この表領域をデフォルト表領域とするTRYユーザーの作成 create tablespace TBS24 datafile '/u01/app/oracle/oradata/orcl/tbs24.dbf' size 100m uniform size 1m ; create user TRY identified by TRY default tablespace TBS24 ; grant connect, resource, dba to TRY ; SQL> -- TAB24表の作成とデータ・ローディング connect TRY/TRY create table TAB24 (COL1 number NOT NULL, COL2 char(1000)) pctfree 10 ; insert /*+append */ into TAB24 select LEVEL, 'hoge'||to_char(LEVEL) from DUAL connect by LEVEL <= 7 * 128 * 62 ; commit; SQL> -- TRYスキーマ内のセグメント・サイズを確認 set linesize 150 col SEGMENT_NAME for a8 col TABLESPACE_NAME for a8 select SEGMENT_TYPE, SEGMENT_NAME, TABLESPACE_NAME, BYTES/1024/1024 from USER_SEGMENTS ; SEGMENT_TYPE SEGMENT_ TABLESPA BYTES/1024/1024 ------------------ -------- -------- --------------- TABLE TAB24 TBS24 63 SQL> -- TAB24表のエクステント、ブロック・アドレスを確認 select owner,segment_name,extent_id,file_id,block_id,blocks from dba_extents where owner='TRY' order by file_id,block_id ; OWNER SEGMENT_ EXTENT_ID FILE_ID BLOCK_ID BLOCKS ------------------------------ -------- ---------- ---------- ---------- ---------- TRY TAB24 0 5 128 128 TRY TAB24 1 5 256 128 TRY TAB24 2 5 384 128 .........
毎度お馴染みの検証前の指の準備運動ですね。このような環境構成をガチャガチャと激しくキーボードの音を鳴らしながら流れるようにSQLを実行できるようになると、たぶん、周囲は貴方をDBAだと認めてくれるでしょう。Flashback Loggingを有効化しているので後々Flashback Databaseでも実行するのか?と推測された方、残念ながらハズレです。これについては演習の最後の方で明らかとなりますので楽しみにしていて下さいね。
この演習1の中では特に新しいSQLは無いと思いますが、DBA_EXTENTSビューだけ補足しておきます。
DBA_EXTENTSビューは、その名の通りエクステント情報を参照することが可能となっています。エクステントはセグメントの次に小さい管理単位でしたよね。エクステントにはセグメント毎に番号が0から順番に振られており、各エクステントがどのデータファイル(FILE_ID)内に格納されているのか、さらには各エクステントに含まれる最初のデータブロックのアドレス(BLOCK_ID)と、そのエクステント内に含まれるブロック数を確認することが可能です。この辺りから、一つのエクステントは必ず一つのデータファイルに格納されている関係を復習することができますね。
例えば、上記の回答例(一部抜粋)では、TRYスキーマのTAB24セグメントの全エクステントが出力されています。0番目のエクステント(EXTENT_ID=0)はFILE_ID=5のデータファイル内に格納されており、データブロックのアドレスが128(=BLOCK_ID)のブロックを先頭として全128個のブロックで構成されていることが理解できます。また、0番目のエクステントは128~255(=128+128-1)というアドレスのブロックが含まれているので、次の1番目のエクステントは256というアドレスのブロックから開始されることも読み取れますね。
2. Buffer Cacheをフラッシュした後、次のddコマンドを実行し、TAB24表のデータブロックをゼロで上書きして下さい。
※ あくまで学習目的での利用に限定し、絶対に本番環境では実行しないでください。
また、これらのコマンドによって生じたいかなる損害に関しても、責任を負いかねます。
$ sqlplus / as sysdba SQL> -- Buffer Cacheのフラッシュ alter system flush buffer_cache ; exit $ dd if=/dev/zero of=/u01/app/oracle/oradata/orcl/tbs24.dbf bs=8192 count=1 seek=140 conv=notrunc
演習1で作成したTAB24表のデータが格納されているTBS24表領域のデータファイルに対してddコマンドを実行することで、140番目のブロックが壊れた状態にします。非常に危険なコマンドなので、ご使用には充分に注意をして下さい。簡単に引数の意味をご紹介しておきますね。
if …入力先ファイル(今回は/dev/zeroを指定しているので全てゼロのデータ)
of…出力先ファイル(入力したデータを書き込む先なので、今回はデータファイルを指定)
bs…一つのデータのサイズ(私のデータベースのBLOCK_SIZE=8192なので、同じサイズを指定)
count…データの数(今回は1ブロックを上書きするので「1」を指定)
seek…出力先ファイルの先頭からスキップするデータの数(今回は140番目のブロックだけを上書きしたい為、「140」を指定)
conv=notrunc…出力先ファイルを切り詰めない(切り詰めてしまうとデータファイル自体が小さくなり、壊れたと認識される)
ちなみに、ddコマンドを実行する前にBuffer Cacheをフラッシュしている理由について補足しておきます。と言っても単純な話ですが、先にddコマンドでディスク上のデータファイルを上書きしたとしても、Buffer Cache上には正常なブロックが存在していますので、DBWRにより、その正常ブロックがディスクへ上書きされれば元の正常な状態に戻ってしまうことになりますからね。
この後、TAB24表へアクセスした場合、次のようにORA-1578が発生することになります。本番環境では絶対に見たくはないエラーですね。しかし、実際に発生する可能性はゼロではないですから、今回の続きの演習を体験して頂くことで冷静に対処出来るスキルを身につけておきましょう!
SQL> select count(*) from TAB24 ;
select count(*) from TAB24
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 5, block # 140)
ORA-01110: data file 5: '/u01/app/oracle/oradata/orcl/tbs24.dbf'
SQL> -- データベースが破損を認識しているブロックの確認
select * from V$DATABASE_BLOCK_CORRUPTION ;
FILE# BLOCK# BLOCKS CORRUPTION_CHANGE# CORRUPTIO
---------- ---------- ---------- ------------------ ---------
5 140 1 0 ALL ZERO
ORA-1578のエラーメッセージとして(file # 5, block # 140)と出力されています。また、ORA-1110のエラーメッセージに障害が発生しているデータファイル番号と名称が出力されています。これにより、TBS24表領域のデータファイル#5に含まれるブロック・アドレス#140のブロックに障害が発生していると読み取ることが可能です。そして、V$DATABASE_BLOCK_CORRUPTIONビューを参照することでデータベースが破損していると認識しているブロックを確認することが可能です。もちろん、アラート・ログにも破損の状況が出力されているので合わせて確認してみてください。
3. RMANを使用して、TBS24表領域のイメージ・コピー・バックアップを取得してください。

おっと、いかがでしょうか?バックアップ処理がORA-19566の出力と共に失敗してしまいましたね。しかし、これは非常に正しい動作です。「何故か?」と問われれば、「ブロックが壊れた状態のバックアップを取得したいですか?」と問い返しましょう。デフォルトの設定において、Recovery Managerはバックアップ処理中に破損しているブロックを一つでも検出した時点で、バックアップ(=確実にリカバリできるか疑わしいバックアップ)を取得することを賢く止めてくれます。そして、これはOracle Databaseのデータブロックの構造(何ビット目に何の情報が格納されている等)を理解しているRecovery Managerだからこそバックアップを止めることが出来たのであって、単純に並んでいるビットをそのまま複製するだけのストレージ装置側のコピー機能では検出することは難しいと思います。
とは言え、バックアップが取得できていないことは事実ですから、急いでデータファイルのブロック破損を修復して正常なバックアップの取得を試みなければなりません。さあ、ワクワクしてきましたね。DBAの腕の見せ所ですよー!(自分で壊しておいて何を言うかって感じですが。。。)
4. RMANのVALIDATEコマンドを実行し、TBS24表領域にその他の破損が含まれていないのかを確認してください。

まずは冷静になりましょうね。
演習3でのバックアップが失敗していますが、この時点ではTBS24表領域のデータファイル内に、一つの破損ブロックが存在したことを検知しただけです。もしかしたら、破損ブロックは一つだけでは無くて複数の破損ブロックが潜在的に存在しているかもしれませんから、データファイルを検証することをお勧めします。今回の演習では、その他の破損ブロックは存在しないことが確認出来ていますね。
データファイルの検証を簡単に実行出来るのがRMANのVALIDATEコマンドとなります。BACKUPコマンドやRESTOREコマンド等のオプションとして指定可能なVALIDATEオプションも存在しますので、そのあたりはバックアップおよびリカバリ・ユーザーズ・ガイドの「VALIDATEを使用してデータベース・ファイルおよびバックアップを確認する手順」以降を参照してみてください。
また、VALIDATEコマンドに対して「CHECK LOGICAL」オプションを追加することも検討してください。このオプションを追加することでデータブロックの物理破損だけでは無く、論理破損も検出することが可能となります。気付いた方もいらっしゃると思いますが、逆を言えば、このオプションを追加しない限り、論理破損を検出することが出来ないと言う事ですね。さらにこの「CHECK LOGICAL」オプションはBACKUPコマンドにも追加することが可能です。もちろん、ご想像通り論理破損を検証する為のCPU消費量は増加しますので、充分な検証した上で検討してみて下さい。
物理破損と論理破損について詳しく解説したいところですが、締め切りに間に合わなくなりそうなので、申し訳ないですが別の機会とさせて下さい。簡単に述べておくと、物理破損の検証はチェックサムを比較するもので、論理破損の検証とは、チェックサムは正しいがOracleデータベースとしてブロック内の情報の整合性が崩れてしまっているかを細かくチェックするものとなります。
5. Data Recovery Advisorを使用して障害内容の確認、復旧手順のアドバイスを受けてください。

障害情報を確認する為には、LIST FAILUREコマンドを使用します。DETAILオプションを追加することで、より詳細な障害情報を確認することが可能です。今回の場合は演習の流れ上、どのような障害が発生しているのかを理解できているので感動は大きくは無いですが、もし万が一本番環境において障害が発生した場合を想像して頂ければ、この情報がどれだけ重宝されるのかを少しだけでも感じて頂けたら幸いです。障害が発生すれば誰しもが興奮状態となり、目の前に見える事象だけを中心に手当たり次第に復旧作業を試みていくものだと思います。そのような場面で、このLIST FAILUREコマンドを実行することでデータベースの内部で発生している問題の全体感を素早く認識することが可能となり、さらには対応しなければならない優先度(Priority)をRecovery Managerが指示をしてくれるのです。

障害状況を把握できた後は、どのように修復していくのかを考えなければなりません。しかし、RMANでの復旧スクリプトをマニュアルも見ずに書き切る自信はありますか?リカバリの達人であれば可能かもしれませんが、私は無いです。。。
そんな私が絶対的に使用するのが「Data Recovery Advisor」機能となります。実行は非常に簡単で、ADVISE FAILUREコマンドを実行するだけです。上記の例では「手動による作業は何も必要無く、Repair Scriptを実行すれば自動で修復できるよ」というように優しくアドバイスしてくれるのです。これは凄いですよね。自動生成されたスクリプトに不信感をお持ちの方は、REPAIR FAILUREコマンドをPREVIEWオプション付きで実行してみてください。修復スクリプト内のコマンドを確認することが出来ます。もちろん、修復スクリプトの場所も出力されていますので、OSのターミナルで確認して頂いても問題ありません。
ちなみに、上記の例では、「recover datafile 5 block 140;」の一文のみです。これはデータファイル#5のブロック#140だけをリカバリするコマンドで、RMANが得意とするブロック単位のリカバリです。このコマンドはデータファイルがオンラインのままで実行することが出来るので、業務影響無く(破損ブロックへアクセスする業務SQLは既に影響が出ていますが)リカバリ作業を実施することが可能です。お客様にもきっと喜ばれるでしょう。
しかし、ここで皆さんに質問を投げ変えてみます。
質問: ブロック単位のリカバリと言う事は、正常なブロックのバックアップからリストアする必要があります。それはどこにあるのでしょうか?演習1からここまで、TBS24表領域のバックアップは取得できていませんよね?
いかがでしょうか?この質問に即答出来た方は、本当に達人だと思います。マニュアルを熟読されて最新テクノロジーを深く理解しているスーパーDBAの方だと思います。質問の答えは、実際にData Recovery Advisorが自動作成した修復スクリプトを実行することで明らかとなります。

どうでしょう?先ほどの質問の答えが見えましたかね?私は初めてこの出力を見たときに度肝を抜かれました。
そうなのです。Flashback logからブロックのイメージを探し出してリストアしていることが上記の実行例から明確に理解出来ます。Flashback LogとはFlashback Databaseを実行する際にだけしか使われないと思い込んでいた方が多いと思いますので、このタイミングでFlashback Logを見直してあげてください。さらに言えば、Data Recovery AdvisorはFlashback Logを使用して修復可能であることを判断したからこそ、この修復スクリプトを提示しています。もし、Flashback Logが存在しない場合は、別の修復スクリプトが提示されることになりますので、お時間がある方は是非試してみてください。演習1でFlashback Loggingを有効化しておいて頂いたのは、これを体験して頂きたかったからなのですね。
このFlashback Logの活用については、マニュアル「バックアップおよびリカバリ・ユーザーズ・ガイド」の「19 ブロック・メディア・リカバリの実行」の章に記述されている「ブロック・メディア・リカバリの前提条件」において、さりげなく紹介されています。マニュアルも偉大ですね。
6. RMANを使用して、TBS24表領域のイメージ・コピー・バックアップの取得を再実行してください。
$ export NLS_DATE_FORMAT="YYYY/MM/DD HH24:MI:SS"; $ rman target / RMAN> backup as copy tablespace TBS24 ; Starting backup at 2013/11/28 18:16:35 using channel ORA_DISK_1 channel ORA_DISK_1: starting datafile copy input datafile file number=00005 name=/u01/app/oracle/oradata/orcl/tbs24.dbf output file name=+FRA/orcl/datafile/tbs24.280.832702597 tag=TAG20131128T181635 RECID=6 STAMP=832702598 channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:04 Finished backup at 2013/11/28 18:16:39
はい、今度は問題無くバックアップを取得することができたと思います。これで大きな山を越えたことにはなりますが、念には念を入れておきましょう。この段階で保証されていることは、バックアップを取得する際に読み込んだ側(データファイル)には破損ブロックが存在していなかったと言う事だけです。バックアップとして書き込んだ側(イメージ・コピー・バックアップ)が正常なのか?書込み時に何かしらの原因で壊れたブロックが書き込まれていないか?という不安は残っているのです。と言う事で、最後の演習を実行しておきましょう。
7. 演習6で取得したTBS24表領域のイメージ・コピー・バックアップが破損していないかをVALIDATEコマンドで確認してください。
$ export NLS_DATE_FORMAT="YYYY/MM/DD HH24:MI:SS"; $ rman target / RMAN> validate check logical copy of tablespace TBS24 ; Starting validate at 2013/11/28 18:17:14 using channel ORA_DISK_1 channel ORA_DISK_1: starting validation of datafile channel ORA_DISK_1: including datafile copy of datafile 00005 in backup set input file name=+FRA/orcl/datafile/tbs24.280.832702597 channel ORA_DISK_1: validation complete, elapsed time: 00:00:03 List of Datafile Copiese ======================= File Status Marked Corrupt Empty Blocks Blocks Examined High SCN ---- ------ -------------- ------------ --------------- ---------- 5 OK 0 4609 12800 236118 File Name: +FRA/orcl/datafile/tbs24.280.832702597 Block Type Blocks Failing Blocks Processed ---------- -------------- ---------------- Data 0 7936 Index 0 0 Other 0 255 Finished validate at 2013/11/28 18:17:17
最後は演習4の復習となります。簡単に実行出来ましたかね?Recovery Managerのコマンドに慣れる必要がありますが、バックアップ(コピー)されたものを対象としたいので、「copy of」句を追加するだけで済みます。演習4で実行したコマンドとの違いを比較して頂ければ一目瞭然だと思います。VALIDATE CHECK LOGICALコマンドは様々な対象をチェックすることが可能なコマンドであることを覚えておいてください。上記の実行例の結果、破損ブロックは検出されなかったので、ようやく安心して眠れそうですね。
さて、いかがでしたでしょうか?
万が一の際に、本当に復旧可能なバックアップを取得していますか?迅速に障害を切り分けて復旧可能な手順やスクリプトを作成する自信はありますか?という疑問に対する回答を体験して頂けたかと思います。Oracle Databaseのデータブロックの構造を理解しているRecovery Managerだからこそ正常なバックアップを取得可能であり、さらに、Data Recovery Advisorにより障害状況に最適な修復スクリプトを自動生成してくれること、少しでもRecovery Managerの魅力を感じて頂けたのであれば嬉しい限りです。
今回も最後まで体験して頂きまして、ありがとうございました。そして、今年一年、皆様のおかげで何とか休載なく続けることが出来ました。長文、乱文にも関わらずお付き合い頂きまして、本当にありがとうございました。来年も引き続き連載させて頂く予定ですので、どうぞよろしくお願い致します。
