Oracle データベース復旧手順書とフルバックアップスクリプト
最近は業務の関係上、Oracle データベースの復旧手順書を作成していました。
Oracle のエンタープライズ分野の主流は RAC 構成になりますが、小規模システムではまだまだシングルインスタンス構成も多いことかと思います。実際システム構成的にはシングルインスタンスの方が遙かにシンプルで運用も楽です。
業務では RAC 構成のシステムを見ていますが、教育という側面からはシングルインスタンスをまずは教えるのが吉です。また部下に DBA の立場を担って貰うことを考えると、最低限知っておいて欲しいのはバックアップ&リカバリ。システムダウン時に活躍するスキルを身につけて欲しいと願います。せっかくいろいろ資料を作ってきたので汎用化できる部分のみ公開しようと思います。
バックアップ方式について言えば最近の主流はもちろん Oracle が提供している Recovery Manager を使ったバックアップ。10g あたりから RMAN が相当使いやすくなってきているので、今から構築なら間違いなく RMAN を使うことをおすすめします。
でも旧来のシステムを使い続けている場合や、小規模なシステムでは、まだまだファイルベースのバックアップ方式をお使いのケースも多いかと思います。これから説明する方法はファイルベースのバックアップを元にリカバリを行う方法になります。RMAN なら書籍でばっちり学ぶことができるので当ブログでは今のところ扱いません。
さて、バックアップについては、いろいろ書籍で学んだりネットの情報で勉強をしてきましたが、いまいちコレというフローチャート的なものが見つかりませんでした。いざマニュアルを書くことになっていろいろ調べてみたら、こんなページを見つけました。ページ自体はずいぶん昔からあったみたいなので、今まで見落としていただけのようです。
Oracle データベースの復旧手順 : http://srgia.com/docs/RecoveringOracle-j.html
この手順書は Oracle 7 時代のもので Server manager 使っていたりするので、今時な Oracle 10g/11g 版に書き直しました。また実際考えられるケースを絞り込んでフローチャートも簡略化しました。
Oracle 10g single instance (アーカイブログモード運用)の復旧フローチャート
各ステップの詳細については別エントリにて記述しますが、下記フローチャートから読み取って欲しい重要なポイントは次の通りです。
- バックアップ&リカバリを考えればアーカイブログ運用は必須。
- 制御ファイルが全損するとデータベースは基本的に復旧不可能な状態になる。
- カレント状態(もしくはアーカイブされていないアクティブ状態)のオンラインREDOロググループが全損するとデータベースは最新の状態まで復旧することができない。
- それ以外の障害であれば、基本的に最新の状態まで復旧することができる。
次に今回のリカバリの元となるバックアップスクリプトの雛形はこちら。※右クリックで DL もできます。
#!/bin/bash
## oracle ユーザでスクリプトを実行して下さい
##=============================================================================
## 各種変数の定義をココで行います。ご自分の環境にあわせて変更下さい。
source /etc/bashrc
NLS_LANG=American_America.JA16EUC
ORACLE_TNS=testdb ## tnsnames.ora で記述したサービス名を指定する
ORACLE_SID=testdb ## SID を指定する
SysIDPW='sys/パスワード as sysdba' ## sqlplus に DBA 権限で接続する際の ID/PW 設定
Mailaddress='your@mail.address.jp' ## メール通知先のアドレスを設定
BackupPoint=(/db/ora) ## アーカイブログ、データファイル(.arc, .dbf)が存在するディレクトリ名を指定。
## 複数指定の場合はスペースを入れて記述する
Tools_dir=/db/tools/backup ## このスクリプトを設置する場所
Log_file=$Tools_dir/fullbackup.log ## ログファイル
Backup_dir=/db/tools/backup ## バックアップファイルを保存する場所
MachineId=`hostname` ## Machine name
##=============================================================================
sleeptime=5
cd $Tools_dir
## BEGIN BLOCK 1 : MODULES=====================================================
## BEGIN BLOCK 1.1 : MailOnErr()-----------------------------------------------
MailOnErr ()
{
Today=`date '+%Y/%m/%d'`
Time=`date '+%T'`
MailTo=$Mailaddress
echo "===================
$0
$Today
$Time
$MachineId has had an error.
Database: ${ORACLE_TNS}
Massage : $message
===================" | mail -s "Error Mail fullbackup_tool" $MailTo
}
## END BLOCK 1.1---------------------------------------------------------------
## BEGIN BLOCK 1.2 : MailOnGood()----------------------------------------------
MailOnGood ()
{
Today=`date '+%Y/%m/%d'`
Time=`date '+%T'`
MailTo=$Mailaddress
echo "===================
$0
$Today
$Time
$MachineId backup has completed.
Database: ${ORACLE_TNS}
===================" | mail -s "Oracle full_backup completed" $MailTo
}
## ENDBLOCK 1.2----------------------------------------------------------------
## BEGIN BLOCK 1.3 : log_write()-----------------------------------------------
log_write ()
{
Today=`date '+%Y/%m/%d'`
Time=`date '+%T'`
echo "$Today-$Time $message" >>$Log_file
}
## ENDBLOCK 1.3----------------------------------------------------------------
## END BLOCK 1 : MODULES=======================================================
message='Begin fullbackup tool'
log_write
## BEGIN BLOCK 2 : ORACLE CHECK================================================
## BEGIN BLOCK 2.1 : Oracle Usable Check---------------------------------------
message='- Oracle Usable Check'
log_write
sqlplus -s <<Eof
$SysIDPW
exit
Eof
if [ $? -ne 0 ]
then
message="Sqlplus could not connect to Oracle. Oracle could not Use!!"
log_write
MailOnErr
exit 1
fi
## END BLOCK 2.1---------------------------------------------------------------
## BEGIN BLOCK 2.2 : The newest Archive redo log is generated------------------
message='- The newest Archive redo log is generated'
log_write
sqlplus -s <<Eof
$SysIDPW
alter system switch logfile;
exit
Eof
if [ $? -ne 0 ]
then
message="could not switch logfile. Oracle could not Use!!"
log_write
MailOnErr
exit 1
fi
## END BLOCK 2.2---------------------------------------------------------------
## BEGIN BLOCK 2.3 : Get Oracle SID Environmental Variable---------------------
message='- Get Oracle SID Environmental Variable'
log_write
if [ -z "$ORACLE_TNS" ]
then
message='ERROR occured!
Can not find $ORACLE_TNS definition - EXITING SCRIPT!'
log_write
MailOnErr
exit 1
fi
## END BLOCK 2.3---------------------------------------------------------------
## END BLOCK 2 : ORACLE CHECK==================================================
## BEGIN BLOCK 3 : Check Database in Archivelog mode and is enabled============
message='- Check Database in Archivelog mode and is enabled'
log_write
sqlplus -s << Eof 2>&1
$SysIDPW
spool archiveloglist.txt;
archive log list
spool off;
exit
Eof
if [ ! -s "archiveloglist.txt" ]
then
message='ERROR occured!
Failed to produce archive log list.'
log_write
MailOnErr
exit 1
fi
DbLogMode=`awk ' /log mode/ {print $4}' archiveloglist.txt`
if [ -z $DbLogMode ]
then
message='ERROR occured!
Can not get Database log mode.'
log_write
MailOnErr
exit 1
fi
if [ "$DbLogMode" != Archive ]
then
message='ERROR occured!
Oracle database is not in Database log Mode.
Please inform your Oracle DBA that the ARCHIVELOG mode must
be set - EXIT SCRIPT!'
log_write
MailOnErr
exit 1
fi
AutoArc=`awk ' /Automatic/ {print $3}' archiveloglist.txt`
if [ -z $AutoArc ]
then
message='ERROR occured!
Can not get Database archival mode.'
log_write
MailOnErr
exit 1
fi
if [ "$AutoArc" != Enabled ]
then
message='ERROR occured!
Oracle database is not in Automatic Archival Mode.
Please inform your Oracle DBA that the ARCHIVELOG mode must
be set - EXIT SCRIPT!'
log_write
MailOnErr
exit 1
fi
## END BLOCK 3=================================================================
## BEGIN BLOCK 4 : Get Oracle Home Environmental Variable======================
message='- Get Oracle Home Environmental Variable'
log_write
if [ -z "$ORACLE_HOME" ]
then
message='ERROR occured!
Can not find $ORACLE_HOME definition - EXITING SCRIPT!'
log_write
MailOnErr
exit 1
fi
## END BLOCK 4=================================================================
## BEGIN BLOCK 5 : Get Oracle Initialisation File Path and File================
message='- Get Oracle Initialisation File Path and File'
log_write
sqlplus << Eof 2>&1
$SysIDPW
spool spfile.txt;
select value from v\$system_parameter where name ='spfile';
spool off;
exit
Eof
if [ ! -s "spfile.txt" ]
then
message='ERROR occured!
Failed to produce spfile location.'
log_write
MailOnErr
exit 1
fi
InitSpFile=`awk '/.ora/ {print $1}' spfile.txt`
if [ -z $DbLogMode ]
then
message='ERROR occured!
Can not get spfile location.'
log_write
MailOnErr
exit 1
fi
InitFile=$Backup_dir/init${ORACLE_TNS}.ora
## END BLOCK 5=================================================================
## BEGIN BLOCK 6 : Database Backup=============================================
## BEGIN BLOCK 6.1 : Begin Backup----------------------------------------------
message='- Begin Backup'
log_write
sqlplus << Eof 2>&1
$SysIDPW
alter database begin backup;
exit
Eof
## END BLOCK 6.1---------------------------------------------------------------
## BEGIN BLOCK 6.2 : Compress All Backup All files-----------------------------
message="- Compress all backup-files."
log_write
rm -f datafiles.txt
for dirname in ${BackupPoint[@]};
do
find $dirname -name *.dbf >>datafiles.txt
find $dirname -name *.arc >>datafiles.txt
done;
cat datafiles.txt | while read line
do
compress_file=`echo $line | awk -F/ '{print $NF}'`
data_file=`echo $line | awk '{print $1}'`
message=" - compress_file : $compress_file"
log_write
tar cvzf $Backup_dir/$compress_file.tar.gz $data_file
if [ $? -ne 0 ]
then
message="ERROR OCCURED!! when $TableSpace : $compress_file copy"
log_write
MailOnErr
exit 1
fi
echo " --> compressed!!"
done;
tar cvfz $Backup_dir/db0.tar.gz /db0/oradata
message="Compress all backup-files."
log_write
## END BLOCK 6.2---------------------------------------------------------------
## BEGIN BLOCK 6.3 : End Backup------------------------------------------------
message='- End Backup'
log_write
sqlplus << Eof 2>&1
$SysIDPW
alter database end backup;
exit
Eof
## END BLOCK 6.3---------------------------------------------------------------
## END BLOCK 6 : End of Database Backup========================================
## BEGIN BLOCK 7 : Configuration File Backup===================================
message='- Configuration File Backup'
log_write
sqlplus << Eof 2>&1
$SysIDPW
create pfile='$InitFile' from spfile;
exit
Eof
## END BLOCK 7=================================================================
## BEGIN BLOCK 8 : Controlfile Backup==========================================
message='- Controlfile Backup'
log_write
sqlplus << Eof 2>&1
$SysIDPW
alter database backup controlfile to '$Backup_dir/controlfile.arc' reuse;
exit
Eof
message="Controlfile Backup Completed."
log_write
## END BLOCK 8=================================================================
## BEGIN BLOCK 9 : Lister & tnsname Backup=====================================
message='- Lister & tnsname Backup'
log_write
cp -f $ORACLE_HOME/network/admin/listener.ora $Backup_dir/listener.ora
cp -f $ORACLE_HOME/network/admin/tnsnames.ora $Backup_dir/tnsnames.ora
## END BLOCK 9=================================================================
MailOnGood
message='END fullbackup tool'
log_write
exit 0


コメントやシェアをお願いします!
TaKuBo
scriptを動かしてみました。
full_backup.shの284にoradataへのパスが直接書いてありました。
ここも先頭の各種変数に移動すると良いと思います。
drk
Kenzさん
script を作成してから随分と月日も経ち、僕の記憶も怪しくなってきておりますが、作成当時には REDO ログを破壊しておいて、わざとエラーが発生する状況を作って試験をしていたような記憶もありますが、定かではありません。
上記のような方法で、実際にエラーが出る状況にして試験をされることをおすすめ致します。
もし宜しければ試験結果を教えていただければ幸いです。
※現状 oracle 業務から離れて日が長いので、僕の oracle スキルが低下中でして・・・
宜しくお願いいたします。
Kenz
はじめまして、Kenzと申します。
フルバックアップのスクリプトを探していたところこちらに辿り着きました。
広く公開される姿勢に頭が下がります。。
ありがたく使わせていただこうと思っております。
ひとつお聞きしたいのですが、BLOCK2.2の中にsqlplusのEXITコードでエラー判定されて
いる部分が有りますが、log switchでエラーが発生したとしてEXITコードは0以外になりますか?
WHENEVER SQLERROR EXIT 1; など入れておかなくてもいいのでしょうか?
自分で試そうと思ったのですが、その部分でうまくエラーを発生させる方法を思いつかな
かったもので質問させていただきました。
よろしくおねがいします。