Мы установили какое-либо приложение, хранилищем данных в котором служит СУБД Oracle. Но вводить систему в производственную эксплуатацию ещё рано. Предварительно необходимо создать надёжную методику резервного копирования и восстановления базы данных.
Одним из самых функциональных средств резервного копирования от Oracle является утилита RMAN. Однако использовать столь сложную систему для резервного копирования зачастую избыточно (если эксплуатируется одна-две базы данных). Кроме того, RMAN, как правило, использует отдельную базу в качестве хранилища своей собственной информации. Чтобы избежать ситуации, когда данные, необходимые для восстановления базы, хранятся в этой же базе, для резервного копирования собственно каталога RMAN необходимо использовать другие средства. Различные универсальные программы резервного копирования, которые могут работать с базами данных Oracle, тоже избыточны или небесплатны. Что же выбрать? Самый простой и экономный способ – решить эту задачу с помощью обычных скриптов и стандартных системных утилит.
Основным критерием качества методов восстановления данных является их адекватность, способность восстановить необходимые данные при любом возможном сбое. Предлагаю вам свой способ решения этой задачи для СУБД Oracle.
Рассмотрим несколько примеров резервного копирования-восстановления без использования RMAN или других утилит.
Возьмём в качестве исходной следующую информацию:
- В тестах будем использовать СУБД Oracle версии 10.2. для ОС Solaris.
- СУБД настроена на работу в режиме АRCHIVELOG.
- Рассмотрим 2 сценария восстановления: полного и неполного.
- Будем исходить из того предположения, что мы восстанавливаем данные на тот же самый сервер (или точную копию рабочего сервера БД, на котором уже установлена ОС, ПО СУБД Oracle, все необходимые исправления и создана необходимая структура каталогов).
- Для наглядности создадим отдельные архивы для файлов данных, управляющих файлов, файлов инициализации и паролей.
- Выполним полную копию базы данных двумя способами:
- с остановкой экземпляра (холодная копия);
- без остановки работы экземпляра (горячая копия).
- Расположение файлов базы данных имеет следующую структуру:
- /ora/oracle/oradata/ORCL – файлы данных;
- /ora/oracle/oradata/Redo-Ctrl/replica0 – первая копия управляющих и журнальных файлов;
- /ora/oracle/oradata/Redo-Ctrl/replica1 – вторая копия управляющих и журнальных файлов;
- /ora/oracle/oradata/log – файлы архивных журналов.
Сделаем полную копию БД двумя вышеуказанными способами:
- Холодная копия базы (cм. листинг 1). Это самый простой пример, он применяется редко. Мы рассмотрим его в целях сравнения с более сложными примерами. $backuponl.sh ORCL /backup/hot
- Горячая копия (см. листинг 2). Создаёт практически аналогичный набор файлов данных, за исключением того, что копии активных журналов redo делать не нужно. Сохраним в архиве одну копию управляющего файла и скрипт control.sql для его пересоздания. $backup.sh ORCL /backup/cold
Сценарии восстановления базы Oracle
Будем имитировать сбой носителя в некоторый момент времени после выполненного резервного копирования, выполняя несколько принудительных переключений активных журналов командой:
SQL> alter system switch logfile;
Затем будем стирать и восстанавливать из архива файлы, принадлежащие БД. Предполагаем, что архивные журналы имеются и доступны для восстановления в каталоге, указанном в параметрах db_recovery_file_dest/log_archive_dest.
Сценарий 1. Клонирование базы данных Oracle из холодной копии
Допустим, нам необходимо запустить базу данных на компьютере с аналогичным программным обеспечением и дисками. Сделаем это с помощью холодной копии. Удалим все файлы базы данных:
my_ora$cd /ora/oracle/oradata/ORCL;find . -type f -exec rm -f {} \; my_ora$cd /ora/oracle/oradata/Redo-Ctrl;find . -type f -exec rm -f {} \;
Проведём восстановление:
my_ora$cd /backup/cold my_ora$tar xvf control.tar my_ora$tar xvf data.tar my_ora$tar xvf dbs.tar my_ora$tar xvf redo.tar my_ora$dbstart
Это практически единственный случай, когда могут пригодиться копии активных (не путать с архивными) журналов базы данных. Во всех остальных случаях необходимо восстановление БД, и устаревшие копии уже не содержат актуальной информации. Гораздо важнее иметь полный (без пропусков) набор архивных журналов. На самом деле в данном случае активные журналы тоже не обязательны.
Часто при создании копии рабочей базы нет необходимости запускать базу именно с опцией NORESETLOGS. Если есть холодная копия, но без копии журналов (файл redo.tar), после восстановления файлов из архива нужно сделать следующее:
my_ora$sqlplus "/ as sysdba" SQL>startup mount Database mounted. SQL> recover database using backup controlfile until cancel; ORA-00279: change 817959 generated at 05/04/2007 09:15:19 needed for thread 1 ORA-00289: suggestion : … Specify log: {<RET>=suggested | filename | AUTO | CANCEL} cancel Media recovery cancelled. SQL>alter database open resetlogs; Database altered.
В этом случае применения архивных журналов не происходит, мы просто обманываем базу данных, заставляя её пересоздать активные журналы.
Сценарий 2. Полное восстановление базы данных Oracle из горячей резервной копии
Смоделируем потерю файлов данных БД. Удалим файлы данных, но не управляющие и журнальные файлы:
my_ora$cd /ora/oracle/oradata/ORCL;find . -type f -exec rm -f {} \;
Проведём восстановление только файлов данных из горячей резервной копии (см. листинг 3):
my_ora$cd /backup/hot my_ora$tar xvf data.tar my_ora$recover.sh ORCL
В зависимости от версии базы данных и операционной системы может понадобиться пересоздать временный файл – это можно сделать, например, скриптом (см. листинг 4):
my_ora$tmprecov.sh ORCL
Сценарий 3. Восстановление управляющих файлов Oracle
Если мы потеряли часть наших управляющих файлов, но сохранилась хотя бы одна копия из указанных в файле init.ora/spfile.ora, нужно скопировать эту копию во все указанные местоположения (например, если пропали файлы в каталоге replica0, нужно скопировать их из каталога replica1). Если пропали все копии управляющих файлов, и только они, необходимо отредактировать файл control.sql (полученный при выполнении горячей копии БД, листинг 2) и выполнить пересоздание управляющего файла. Если такого скрипта мы заранее не создали, тогда нам остаётся только воспользоваться сделанными ранее копиями управляющих файлов:
my_ora$tar xvf control.tar my_ora$cp control01.ctl /ora/oracle/oradata/Redo-Ctrl/replica0/control01.ctl my_ora$cp control01.ctl /ora/oracle/oradata/Redo-Ctrl/replica1/control03.ctl my_ora$sqlplus "/ as sysdba" SQL>startup mount SQL> alter database backup controlfile to trace as 'control.sql' ; SQL>shutdown SQL>exit
Затем отредактировать и выполнить скрипт. Существует ещё один способ: скопировать текущий активный журнал в местоположение log_archive_dest в формате log_archive_format, выполнить неполное восстановление и открыть базу с опцией RESETLOGS (потери зафиксированных транзакций при этом не произойдёт, но нумерация архивных журналов начнётся сначала).
Сценарий 4. Восстановление БД Oracle при утере копии добавленного файла
После выполнения резервного копирования был добавлен один файл базы данных (см. листинг 5), и впоследствии произошла поломка жесткого диска. А копии управляющего файла и нового файла данных мы сделать не успели. Если попытаться провести восстановление базы из существующих резервных копий, восстановление будет идти только до момента создания нового файла, после чего возникнет ошибка:
SQL> alter database recover automatic using backup controlfile; alter database recover automatic using backup controlfile * ERROR at line 1: ORA-00283: recovery session canceled due to errors ORA-01244: unnamed datafile(s) added to control file by media recovery
Я думаю, самым надёжным способом избежать подобной ситуации будет иметь достаточное количество реплик файла управления и всегда делать резервную копию добавляемых файлов. Если же такая ситуация произошла, можно воспользоваться последовательностью команд, представленной в листинге 6. Отмечу, что это не готовый скрипт, а лишь примерная последовательность команд с комментариями, поскольку невозможно заранее предугадать номера и названия файлов данных.
Сценарий 5. Восстановление базы Oracle при потере активных журналов
Если потеряны не все группы REDO, а только какая-то одна реплика REDO файлов БД, то остановки базы при этом не происходит. В этом случае журналы можно пересоздать или при перезагрузке скопировать файлы из одного каталога в другой. Если же мы потеряли все файлы REDO (или хотя бы как минимум активную группу), полное восстановление невозможно. Остаётся вариант неполного восстановления и последующий запуск БД с опцией RESETLOGS. В этом случае возможна потеря зафиксированных транзакций, и произойдёт сброс последовательности архивных журналов.
Смоделируем ситуацию:
my_ora$dbshut my_ora$cd /ora/oracle/oradata/Redo-Ctrl my_ora$find . –type f -name \*.log –exec rm –f {} \; my_ora$sqlpplus "/ as sysdba" SQL>startup mount SQL>recover database until cancel ... cancel SQL> alter database open resetlogs; SQL> exit
Из этого примера видно, как важно иметь хотя бы две реплики активных журналов базы данных (redo log). В случае их уничтожения – потеря информации (пусть иногда и допустимая) неизбежна. Её можно лишь минимизировать, например установив параметр archive_lag_target (его минимальное значение – 60 секунд).
Сценарий 6. Восстановление базы Oracle только по резервной копии и архивным журналам
Исходная БД погибла, остались резервная копия и архивные журналы. В данном случае, если нет специальных систем аппаратного зеркалирования управляющих файлов и журналов, возможно только неполное восстановление и последующий запуск с опцией RESETLOGS. Последовательность шагов во многом аналогична сценарию 2, но есть отличия: восстанавливаются не только файлы данных, но и управляющие файлы, файлы инициализации и паролей.
my_ora$tar xvf data.tar my_ora$tar xvf control.tar my_ora$tar xvf dbs.tar
Потом, поскольку активные журналы потеряны, производится неполное восстановление (см. листинг 7). БД открывается с опцией RESTLOGS.
my_ora$recovincomplett.sh ORCL
Заключение
Подводя итоги рассмотренных сценариев, хотелось бы отметить основные моменты:
- Резервная копия должна быть обязательно полной (все файлы данных, все архивные журналы, файлы управления, инициализации и пароли).
- При восстановлении производственной базы нужно стараться не допустить случая неполного восстановления (с опцией RESETLOGS), поскольку это изменяет последовательную нумерацию журналов и есть риск потери данных. Вариант восстановления БД с переходом через точку RESETLOGS вообще-то существует, но он довольно громоздкий. Не стоит усложнять самому себе жизнь. Описание этого метода приводится, например, в книге «Oracle Backup & Recovery Handbook» [2, глава 10].
- Чтобы избежать случая неполного восстановления, следует беречь активные журналы. В большинстве случаев их резервная копия невозможна, необходимо иметь несколько реплик, размещать их на RAID1 и т. п.
- Копировать активные журналы REDO, можно только при холодной копии, и нужны они только для создания клона БД.
- Не менее важно беречь и управляющие файлы. Их можно, как правило, пересоздать, но это требует времени, потеря хотя бы одной копии управляющего файла делает невозможным старт БД.
- Для восстановления необходимо иметь архивные журналы, их тоже желательно включать в резервную копию, или настроить файл параметров так, чтобы журналы архивировались в несколько мест сразу, например, на локальный диск и на сетевой. (Параметр LOG_ARCHIVE_DEST_N.)
- Холодная и горячая резервные копии БД для восстановления пригодны одинаково, нельзя сказать, что горячая копия не позволяет сделать то, что позволяет холодная. За исключением случая клонирования. Горячая копия всегда нуждается в применении впоследствии команды «recover». Для этого не обязательно, но полезно после завершения копии принудительно переключить активный журнал, чтобы не ждать, когда он переключится сам, а сразу приступать к клонированию базы данных.
- Ну и напоследок, моё трепетное отношение к полному восстановлению относится в основном к производственным базам. Если необходимо восстаноить БД на какой-то момент времени в прошлом, то такой сценарий предусматривает именно неполное восстановление.
Приложение
Листинг 1. Холодная копия БД (файл backup.sh)
#!/bin/sh #< if [ $# -ne 2 ] then echo "script needs two parameters: \${ORACLE_SID} <dest dir>" exit; fi # ORACLE_SID=${1};export ORACLE_SID copydir=${2};export copydir #Create lists of files. #Regular database files datalist=`sqlplus -s "/ as sysdba" <<EOF set heading off set pagesize 0 set linesize 300 set feed off select file_name from dba_data_files ; exit ; EOF` #Temporary files templist=`sqlplus -s "/ as sysdba" <<EOF set heading off set pagesize 0 set linesize 300 set feed off< select file_name from dba_temp_files; exit; EOF` #Control files ( copy all ) controlist=`sqlplus -s "/ as sysdba" <<EOF set heading off set pagesize 0 set linesize 300 set feed off select name from v\\$controlfile ; exit ; EOF` #Online Redo logs. redolist=`sqlplus -s "/ as sysdba" <<EOF set heading off set pagesize 0 set linesize 300 set feed off select member from v\\$logfile ; exit ; EOF` # sqlplus "/ as sysdba" <<EOF shutdown immediate exit; EOF cd ${copydir} tar cvf data.tar ${datalist} ${templist} tar cvf control.tar ${controlist} tar cvf redo.tar ${redolist} tar cvf dbs.tar ${ORACLE_HOME}/dbs/init${ORACLE_SID}.ora \ ${ORACLE_HOME}/dbs/spfile${ORACLE_SID}.ora \ ${ORACLE_HOME}/dbs/orapw${ORACLE_SID} sqlplus "/ as sysdba" <<EOF startup exit; EOF #
Листинг 2. Горячая копия БД (файл backuponl.sh)
#!/bin/sh # if [ $# -ne 2 ] then echo "script needs two parameters: \${ORACLE_SID} <dest dir>" exit; fi # ORACLE_SID=${1};export ORACLE_SID copydir=${2};export copydir #Make lists of files for backup. #data files datalist=`sqlplus -s "/ as sysdba" <<EOF set heading off set pagesize 0 set linesize 300 set feed off select file_name from dba_data_files ; exit ; EOF` #Controlfile make one copy and one trace controlist=`sqlplus -s "/ as sysdba" <<EOF set heading off set pagesize 0 set linesize 300 set feed off select name from v\\$controlfile where rownum=1; exit ; EOF` controldir=`dirname $controlist` # sqlplus "/ as sysdba" <<EOF alter database begin backup; exit; EOF cd ${copydir} tar cvf data.tar ${datalist} # Init & passwd files tar cvf dbs.tar ${ORACLE_HOME}/dbs/init${ORACLE_SID}.ora \ ${ORACLE_HOME}/dbs/spfile${ORACLE_SID}.ora \ ${ORACLE_HOME}/dbs/orapw${ORACLE_SID} sqlplus "/ as sysdba" <<EOF alter database end backup; alter database backup controlfile to '$controldir/conbackup.ctl' reuse ; alter database backup controlfile to trace as '$controldir/control.sql'; alter system archive log current ; exit; EOF # for i in ${controlist} do # cp /tmp/conbackup.ctl ${copydir}/`basename ${i}` tar cvf control.tar $controldir/conbackup.ctl $controldir/control.sql rm -f $controldir/conbackup.ctl rm -f $controldir/control.sql done #
Листинг 3. Полное восстановление БД (файл recover.sh)
#!/bin/sh # if [ $# -ne 1 ] then echo "script needs one parameter: \${ORACLE_SID}" exit; fi # ORACLE_SID=${1};export ORACLE_SID sqlplus "/ as sysdba" <<EOF startup mount; alter database recover automatic ; alter database open; exit; EOF
Листинг 4. Добавление к БД нового временного файла (файл tmprecov.sh)
#!/bin/sh # if [ $# -ne 1 ] then echo "script needs one parameter: \${ORACLE_SID}" exit; fi # ORACLE_SID=${1};export ORACLE_SID # #Temporary files templist=`sqlplus -s "/ as sysdba" <<EOF set heading off set pagesize 0 set linesize 300 set feed off select file_name from dba_temp_files; exit; EOF` for i in ${templist} do sqlplus "/ as sysdba" <<EOF alter database tempfile '$i' drop INCLUDING DATAFILES; ALTER TABLESPACE "TEMP" ADD TEMPFILE '$i' size 25M autoextend on; exit; EOF done
Листинг 5. Восстановление БД при утере копии вновь добавленного файла и файлов управления (файл addfile.sh)
#!/bin/sh # #Script for adding new dstsfile sqlplus "/ as sysdba" <<EOF alter tablespace users add datafile '/ora/oracle/oradata/ORCL/users02.dbf' size 20M; exit EOF
Листинг 6. Неполное восстановление при потере активных журналов (файл nofile.sql)
connect / as sysdba startup mount alter database recover automatic using backup controlfile -- --ERROR at line 1: --ORA-00283: recovery session canceled due to errors --ORA-01244: unnamed datafile(s) added to control file by media recovery --ORA-01110: data file 5: '/ora/oracle/oradata/ORCL/users02.dbf' -- alter database backup controlfile to trace as 'dmpctl.sql'; select name from v$datafile where file#=5; --NAME ------------------------------------------------ --/ora/oracle/dbs/UNNAMED00005 -- alter database create datafile '/ora/oracle/dbs/UNNAMED00005' as '/ora/oracle/oradata/ORCL/users02.dbf'; -- Make changes in scripts for recreate controlfile. host vi dmpctl.sql -- shutdown @dmpctl.sq
Листинг 7. Неполное восстановление при потере активных журналов (файл recovincomplett.sh)
#!/bin/sh # if [ $# -ne 1 ] then echo "script needs one parameter: \${ORACLE_SID}" exit; fi sqlplus "/ as sysdba" <<EOF startup mount; alter database recover automatic using backup controlfile; alter database open resetlogs; exit; EOF
Список литературы
- Oracle Database Backup and Recovery Advanced User's Guide 10g Release 2 (10.2) Part Number B14191-02 – http://download-uk.oracle.com/docs/cd/B19306_01/backup.102/b14191/toc.htm.
- Oracle8i Backup & Recovery Handbook, Rama Velpuri and Anand Adkoli.McGraw-Hill/OsborneMedia; 4Rev Ed edition (November 14, 2000).