しばちょう先生の試して納得!DBAへの道
第19回 フラッシュバック・データベースによる論理障害からの復旧

■しばちょう先生による技術解説セミナー。動画、資料を公開中です。

みなさん、こんにちは。 “しばちょう”こと柴田長(しばた つかさ)です。

この原稿提出の締め切りが残り7~8時間というところでしょうか?何とか間に合わせようと終電一本前の電車の中で、今まさに執筆している最中でございます。夜型の私はここからが本番と言う事で、張り切って行きたいと思います。

突然ですが、皆さんはMAAという単語をご存じでしょうか?もしご存じあれば、かなりのOracle通であることは間違いないと思います。正式名称はOracle Maximum Availability Architectureですが、このような名称の製品は存在しません。MAAとはOracleが推奨する高可用性テクノロジー、ベストプラクティスの集合体となります。最近では、このMAAに特化したマニュアルも公開されておりますので、是非ご参照頂ければと思います。

そして、今回から複数回でご紹介するフラッシュバック・データベースはMAAの中でも重要な機能であり、もしかしたらDBAの皆さんのオペミスを華麗に救ってくれるであろう、転ばぬ先の杖と呼ぶにふさわしい頼もしい奴です。次のケースにおいて、フラッシュバック・データベースを用いてリカバリすることが可能であり、バックアップ・ファイルをリストアする操作が不要であり、短時間に過去の時点でのデータベースの状態に巻き戻すことができるのです。

■ リカバリ可能なオペレーション
✓ DML処理(INSERT、DELETE、UPDATE)
✓ TRUNCATE
✓ スキーマ・ユーザーの削除(DROP USER)

もう少しだけ興味を持って頂きたいので、このフラッシュバック・データベースの伝説的な活用話をご紹介させて頂きますね。カット・オーバー直前のデータ初期移行を開始して数週間経過した時点で、実行する処理の順番を誤ってしまいデータを論理的に破壊してしまったとのこと。直近のバックアップを取得しておらず、データ移行作業を初めから実行し直すしかなく、カット・オーバー日の延期か?という事態にまで陥った際に、フラッシュバック・データベースで巻き戻せばいいじゃないか?と立ち上がった男がいました。もちろん私では無いですが、その男は見事に論理破壊前の正常な状態にデータを巻き戻し、無事予定通りにカット・オーバーを実現させたとのこと。非常にカッコイイですよね。憧れますよね。

そのように思って頂けた方は、是非とも今回の演習を通して、フラッシュバック・データベースの基本を学んで頂ければと思います。以下の演習をOracle Database 11g Release 2 Enterprise Editionのデータベースで試してみてください。

【今回ご紹介するネタ一覧(逆引き)】

  • 高速リカバリ領域の設定(演習2)
  • Flashback Loggingの有効化と確認(演習3)
  • Flashback Log量の確認(演習4、5)
  • Flashback Databaseの実行(演習6)

1. 第一カラムが主キーでNUMBER型のCOL1、第二カラムがCHAR(100)型のCOL2列である表TAB19を作成し、初期データ100万件をロードしてください。

sqlplus TRY/TRY
SQL>
create table TAB19 (COL1 number NOT NULL, COL2 char(100));
insert /*+append */ into TAB19
  select LEVEL, 'hoge'||to_char(LEVEL) 
      from DUAL connect by LEVEL <= 1000000 ;
commit;

create unique index IDX_TBL19_COL1 on TAB19(COL1) ;
alter table TAB19 add primary key (COL1) using index ;

毎度毎度の事前準備ですね。実は前回と全く同じSQLなのですが、検証慣れをしていないと意外と何も見ずに書くことが難しかったりするのですよね。気をつけねばなりませんよー。

2. 高速リカバリ領域を設定してください。あわせて、データベース・ログ・モードをアーカイブ・モードに設定/確認してください。

sqlplus / as sysdba
SQL>
alter system set db_recovery_file_dest='+FRA'   scope=spfile ;
alter system set db_recovery_file_dest_size=2g  scope=spfile ;

shutdown immediate ;
startup mount ;
alter database archivelog ;
archive log list

データベース・ログ・モード     アーカイブ・モード
自動アーカイブ                 有効
アーカイブ先                    USE_DB_RECOVERY_FILE_DEST
最も古いオンライン・ログ順序   93
アーカイブする次のログ順序    95
現行のログ順序               95

SQL>
alter database open ;
show parameter db_recovery_file_dest

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_recovery_file_dest                string      +FRA
db_recovery_file_dest_size           big integer 2G

フラッシュバック・データベースを使用する為には、「Flashback Loggingを有効にする」or 「保証付きリストアポイントを作成する」というどちらか一方、もしくは両方を選択する必要があります。この二つの違いの詳細については次回説明を予定しておりますが、量は異なりますが、どちらの場合でもフラッシュバック・ログ(更新対象ブロックの更新前のブロック・イメージ)が生成されるという動作に違いはありません。そして、このフラッシュバック・ログは「高速リカバリ領域」に自動的に生成される仕様である為、フラッシュバック・データベースを使用するには、絶対的に高速リカバリ領域を設定しなければならないのです。

とは言え、高速リカバリ領域の設定とは具体的には次の二つの初期化パラメータを設定するだけです。
✓ db_recovery_file_dest : 高速リカバリ領域の場所を指定
✓ db_recovery_file_dest_size : 高速リカバリ領域のサイズを指定
また、フラッシュバック・データベースを使用する為には、アーカイブ・モードでの運用も必須となりますので、このタイミングでアーカイブ・モードに設定されているかを「archive log list」コマンドを実行して確認しておきましょう。

3. Flashback Loggingを有効化してください。

sqlplus / as sysdba
SQL> alter database flashback on ;
*
行1でエラーが発生しました。:
ORA-38706: FLASHBACK DATABASEロギングをオンにできません。 ORA-38708:
最初のフラッシュバック・データベース・ログ・ファイル用の領域が不足しています

高速リカバリ領域とアーカイブ・モードの設定が済んだので、いざ、Flashback Loggingを有効化してみたら?あれ? いきなりエラーが発生してしまいましたね。どうも演習2で設定したdb_recovery_file_dest_sizeパラメータの2GBが小さいと言う事なので、改めて10GBに変更してリトライしてみましょう。

sqlplus / as sysdba
SQL> alter system set db_recovery_file_dest_size=10g  scope=both ;
SQL> alter database flashback on ;

データベースが変更されました。


SQL> select FLASHBACK_ON from V$DATABASE ;

FLASHBACK_ON
------------------
YES


SQL> show parameter db_flashback_retention_target 

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_flashback_retention_target        integer     1440

はい、無事にFlashback LoggingをONにすることができましたね。実際にONになっているのかは、ディクショナリ・ビューV$DATABASEのFLASHBACK_ON列を参照するだけで確認することができます。

また、UNDOレコードと同様に、フラッシュバック・ログの保持期間を設定する初期化パラメータdb_flashback_retention_targetが存在しています。こちらは要件に合わせて設定変更する必要があります。もちろん、保持期間を長くすれば長くするほど必要とされる高速リカバリ領域のサイズは大きくなりますが、db_recovery_file_dest_sizeパラメータの方が優先される点にご注意ください。つまり、フラッシュバック・ログの量が多過ぎる場合にはdb_flashback_retention_targetパラメータで指定した保持期間が守られず、フラッシュバック・ログが自動的に削除(パージ)されていく動作となります。

4. 現時点でのFlashback Logの量を確認した後、TAB19表の特定のレコードを1000000回更新して下さい。

sqlplus / as sysdba
SQL> set linesize 150 pages 5000
select * from V$FLASHBACK_DATABASE_LOG ;

OLDEST_FLASHBACK_SCN OLDEST_F RETENTION_TARGET FLASHBACK_SIZE ESTIMATED_FLASHBACK_SIZE
-------------------- -------- ---------------- -------------- ------------------------
             1445113 13-06-26             1440       31883264                        0


set linesize 150 pages 5000
col NAME for a40
select * from V$FLASHBACK_DATABASE_LOGFILE ;

NAME                                      LOG# THREAD# SEQ    BYTES FIRST_C FIRST_TI TYPE
---------------------------------------- ----- ------- --- -------- ------- -------- ---------
+FRA/orcl/flashback/log_1.256.819152367      1       1   1 15941632 1445113 13-06-26 NORMAL
+FRA/orcl/flashback/log_2.257.819152369      2       1   1 15941632       0          RESERVED


SQL> connect TRY/TRY
select * from TAB19 where COL1=100 ;

      COL1 COL2
---------- -------------------
       100 hoge100

begin
  for i in 1..1000000 loop
    update TAB19 set COL2='updated'||i where COL1=100 ;
    commit ;
  end loop ;
end ;
/

select * from TAB19 where COL1=100 ;

      COL1 COL2
---------- -------------------
       100 updated1000000

では、フラッシュバック・ログを生成してみましょう。フラッシュバック・ログとは、演習2の解説の中でさらっと書いてしまっていたのですが、実際には更新対象ブロックの更新前のブロック・イメージとなります。よって、UPDATE文等によりブロックが更新される際に、更新前のブロックがフラッシュバック・ログとして退避されると考えて頂ければ間違いは無いです。よって、この演習では、同じブロックを100万回UPDATEすることで、フラッシュバック・ログがどの程度生成されていくのかを確認してみます。

100万回のUPDATEを実行する前のフラッシュバック・ログの量は、ディクショナリ・ビューV$FLASHBACK_DATABASE_LOGもしくは、V$FLASHBACK_DATABASE_LOGFILEで確認することが可能です。前者のV$FLASHBACK_DATABASE_LOGにおいては、FLASHBACK_SIZE列の値を参照することでおおよその量を確認することができますが、正確な量は後者のV$FLASHBACK_DATABASE_LOGFILEのTYPE列が「NORMAL」と表示されているレコードのBYTES列の合計となります。各ビューの問合せ結果を見比べて頂くと一目瞭然ですが、「RESERVED」となっている「まだ書き込まれていないけど準備してあるフラッシュバック・ログファイル」のサイズも、前者のV$FLASHBACK_DATABASE_LOGのFLASHBACK_SIZE列の値には加算されてしまっています。厳密にいえば、後者のV$FLASHBACK_DATABASE_LOGFILEにおいてもNORMALとなっている一つ目のフラッシュバック・ログファイル内にフラッシュバック・ログがキッチリと格納されている状態かどうかは不明確なので、数十MB単位で実際のフラッシュバック・ログの量と確認可能なサイズの差は生まれてしまいます。

さて、この回答例では、COL1列が100のレコードのCOL2列の値を100万回UPDATEしていますが、UPDATE開始前の値は「hoge100」だったのに対し、UPDATE後の現時点では「updated1000000」となっていることが確認できていますね。よって、この後の検証としては、フラッシュバック・データベースでUPDATE前の値である「hoge100」に巻き戻せるのかが焦点となるという点に注目してください。

5. 演習4の更新処理中に生成されたFlashback Logの量を確認してください。

sqlplus / as sysdba
SQL> 
SQL> set linesize 150 pages 5000
select * from V$FLASHBACK_DATABASE_LOG ;

OLDEST_FLASHBACK_SCN OLDEST_F RETENTION_TARGET FLASHBACK_SIZE ESTIMATED_FLASHBACK_SIZE
-------------------- -------- ---------------- -------------- ------------------------
             1445113 13-06-26             1440      134627328               5175582720


set linesize 150 pages 5000
col NAME for a40
select * from V$FLASHBACK_DATABASE_LOGFILE ;

NAME                                     LOG# THREAD# SEQ    BYTES FIRST_C FIRST_TI TYPE
---------------------------------------- ---- ------- --- -------- ------- -------- ---------
+FRA/orcl/flashback/log_1.256.819152367     1       1   1 15941632 1445113 13-06-26 NORMAL
+FRA/orcl/flashback/log_2.257.819152369     2       1   2 15941632 1543943 13-06-26 NORMAL
+FRA/orcl/flashback/log_3.261.819153445     3       1   3 15941632 1750433 13-06-26 NORMAL
+FRA/orcl/flashback/log_4.265.819153475     4       1   4 20463616 2121017 13-06-26 NORMAL
+FRA/orcl/flashback/log_5.271.819153527     5       1   5 28229632 2547495 13-06-26 NORMAL
+FRA/orcl/flashback/log_6.278.819153583     6       1   1 38109184       0          RESERVED


select name,value from v$sysstat where name = 'flashback log write bytes';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
flashback log write bytes                                          74276864

ちょうど良い機会なので、フラッシュバック・データベースを実行する前に、100万回のUPDATE処理でどの程度のフラッシュバック・ログが生成されたのかを確認しておきましょう。V$FLASHBACK_DATABASE_LOGの出力結果を比較することで約100MB(=134627328 - 31883264)増加しています。とは言え、演習5の解説でも述べたように、この値は正確ではありませんよね。もうひとつのビューであるV$FLASHBACK_DATABASE_LOGFILEを使う事でもう少し小さな値、約80MBの増加量であったことが計算できますね。

ここでおや?と感じられた方、素晴らしく鋭いです。ブロックサイズの8KB、100万回のUPDATE、生成されたフラッシュバック・ログのサイズである約80MB。これらを計算すると、どうも全ての更新前ブロックのイメージがフラッシュバック・ログに退避されてはいないようですね。マニュアルにも記載されているのですが、フラッシュバック・データベースは、このフラッシュバック・ログだけではなく、アーカイブRedoログやオンラインRedoログも組み合わせて過去の状態へ巻き戻す仕組みとなっています。内部仕様となりますので詳細にご説明することはできませんが、このFlashback Logの適用 + Redoによるロールフォワードという仕組みによって、Flashback Databaseの機能が実現されていると考えることができそうですね。

おまけですが、フラッシュバック・ログの生成量を確認する方法をご紹介しておきます。それは、統計情報「flashback log write bytes」です。v$sysstatはインスタンス起動後からの累積値が記録されているので、UPDATE前にも確認しておくことでその差を厳密に計測することが可能になります。

6. 演習4での更新処理前のレコードの状態にFlashback Databaseで巻き戻してください。

sqlplus / as sysdba
SQL>
shutdown immediate ;
startup mount ;
flashback database to TIMESTAMP(SYSDATE - 30/(24*60) ) ;

フラッシュバックが完了しました。

alter database open READ ONLY ;

SQL> connect TRY/TRY
select * from TAB19 where COL1=100 ;

      COL1 COL2
---------- ----------------
       100 hoge100

SQL> connect / as sysdba
shutdown immediate ;
startup mount ;
alter database open RESETLOGS;

さて、いよいよフラッシュバック・データベースを使用して、UPDATE前の状態にデータベース全体を巻き戻してみましょう。

今回の解答例では「30分前の状態に戻す」為のコマンドとして、「TIMESTAMP(SYSDATE - 30/(24*60) )」を指定しています。この部分の指定の仕方は幾つか方法が有りますので、マニュアル「バックアップおよびリカバリ・ユーザーズ・ガイド」もしくは、【Oracle DBA & Developer Day 2012】高可用性システムに適した管理性と性能を向上させる ASM と RMANの魅力のスライド50ページ以降をご確認下さい。

フラッシュバック・データベースを実行した後は、本当に目的の状態に巻き戻っているかを確認する必要があります。そのためには一度「READ ONLY」モードでデータベース・インスタンスをオープンして実際に問合せを実行してみます。今回の解答例では、100万回のUPDATE前の状態である「hoge100」に巻き戻っていることが確認できています。

期待される状態であれば、RESETLOGSを付けてオープンし直すことで、巻き戻した状態を確定させることができますが、もし巻き戻しが足りなかった場合には、マウント状態でflashback database文を再実行すれば良いだけです。逆に、巻き戻し過ぎてしまっていた場合には、recover database文で任意の時点までロール・フォワードすれば良いのです。

さて、いかがでしたでしょうか? 今回はフラッシュバック・データベースの触りだけのご紹介となってしまいましたが、少しは便利そうな機能だなと感じて頂けたのであれば幸いです。近年、テラバイト級のデータを保有しているデータベースが非常に多くなってきていると感じています。そのようなデータベースにおいては、バックアップ・ファイルのリストアに要する時間は非常に長く、お客様のサービスレベルの低下につながる可能性が高くなってきています。これに対するチューニング方法はいくつか存在はしていますが、データの論理破損であれば、このフラッシュバック・データベースを活用することで短時間での復旧を実現することが可能になります。次回以降は、もう少し踏み込んでご紹介していきたいと思いますので、どうぞよろしくお願いします。

追伸 前回の記事の最後の文章を読み直すと、自分が一番成長していないなと感じてしまいます。。。

img_sibacho.gif ■しばちょう先生より
データベース・スペシャリストとして、Oracle GRID Centerの設立当初からOracleの持つ最新技術をパートナー各社と共同で検証し、これまでにリアルなパフォーマンスに裏付けられた数多くのWhite Paperを執筆してきました。現在は大規模案件の現場を訪問し、お客様のシステムに最適なソリューション・デザインの提案やパフォーマンス・トラブルの問題解決に従事しております。

これらの提案やトラブル解決を行う上で痛感していることは、SIer時代の開発現場やOracle GRID Centerでの実機検証の経験が確実に生かされているということです。経験しているからこそ、マニュアル棒読みの機能紹介では留まらず、瞬時にその機能の適用シナリオも含めて自信を持って自分の言葉(お客様に合わせた言葉)でお客様に提案できますし、早期にトラブル原因の当たりを付けたり解決のアイディアを閃いたりすることが可能になっていると思っています。

今回の連載は、正に体験して頂くことが主軸となります。単純な機能紹介ではなく手を動かして理解を深めて頂けるような連載にしていきたいと考えております。内容としては私が新人をDBAに育てる際に使用する課題をカスタマイズしたものであり、レベルとしては初級~中級を想定しております。これからDBAを目指される方、実機での作業から数年間離れられている方等々、多くの方にご活用頂ければ幸いです。