しばちょう先生の試して納得!DBAへの道 indexページ▶▶
みなさん、こんにちは。 “しばちょう”こと柴田長(しばた つかさ)です。
この原稿提出の締め切りが残り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文で任意の時点までロール・フォワードすれば良いのです。
さて、いかがでしたでしょうか? 今回はフラッシュバック・データベースの触りだけのご紹介となってしまいましたが、少しは便利そうな機能だなと感じて頂けたのであれば幸いです。近年、テラバイト級のデータを保有しているデータベースが非常に多くなってきていると感じています。そのようなデータベースにおいては、バックアップ・ファイルのリストアに要する時間は非常に長く、お客様のサービスレベルの低下につながる可能性が高くなってきています。これに対するチューニング方法はいくつか存在はしていますが、データの論理破損であれば、このフラッシュバック・データベースを活用することで短時間での復旧を実現することが可能になります。次回以降は、もう少し踏み込んでご紹介していきたいと思いますので、どうぞよろしくお願いします。
追伸 前回の記事の最後の文章を読み直すと、自分が一番成長していないなと感じてしまいます。。。
