Мой способ резервного копирования БД Oracle на Windows

в 4:56, , рубрики: backup, oracle, windows, метки: , ,

Доброго времени суток всем.
Работаю администратором баз данных далеко не первый год, но всегда работал в больших компаниях. За это время работал с Linux, Solaris, HP-UX. Но примерно год назад попал в небольшую компанию, и о ужас, все сервера на Windows, как такового резервного копирования не делалось, точнее только экспорт.

Было необходимо делать нормальный физический backup, решил писать скрипт, как требования для себя выделил несколько моментов:

  1. Скрипт должен работать должен работать с любой ОС начиная с win 2003 сервер, при этом не требовать дополнительного софта.
  2. Скрипт должен работать на любом Oracle начиная с версии 9i, при этом делать полный, инкрементальный бэкап, и бэкап архивлогов.
  3. Скрипт должен быть, как можно проще, переносим с сервера на сервер, желательно чтобы это был один файл.

Первая мысль была поставить cygwin или perl, сделать Windows похожей на unix, но тогда будут трудности с переносом на другие сервера. Решил писать простой пакетный файл ms-dos, правда ничего сложнее, чем copy con my_text.txt в батниках я не писал. Реализация пункта 3, вообще получилось кошмаром, у меня нет встроенных документов, я не могу написать:

sqlplus "/ as sysdba" << SQL
select sysdate from dual;
SQL

Решил все дополнительные скрипты записывать во временные файлы, а вывод програм в переменные. Неожиданно вылезла ещё одна проблема если переменная не задана echo %AAA% выводит %AAA%, пришлось переменной присваивать пробел.
Для 10g и выше архивлоги собираются в бэкапсет, так как есть компрессия. Для 9i архивлоги копируются как есть, так как нет команды catalog, при восстановление из нескольких бекапсетов придется восстанавливать контрол файлы. При полном бэкапе все содержимое директории DEST переносится в OLD. И вот что у меня в итоге получилось:

echo off
REM version 1.4
REM Использовать "rman_Backup_DB.cmd [t|a|d|0-1]" 
REM 0-1 уровень инкрементального бекапа (0 - полный)
REM a бекап только архив логи
REM t или ничего тест, проверяется запуск sqlplus,rman, запись в DEST
REM d быстрое удаление архивлогов, если место уже кончилось, после этого НЕОБХОДИМ ПОЛНЫЙ БЕКАП

REM -------------------Далее задаются переменные---------------------------------

REM Директория назначения
set DEST=\SMB_servershare

REM Директория назначения Старых файлов
set OLD=%DEST%OLD

set ORACLE_SID=ORCL
set ORACLE_HOME=C:APPorabaseproduct11.2.0dbhome_1
set NLS_LANG=AMERICAN_AMERICA.CL8MSWIN1251
set NLS_DATE_FORMAT=YYYY.MM.DD HH24.MI.SS

REM COMPRESS=пробел для 9i и ниже (пробел обязательно)
REM для 10 и выше =as compressed backupset 
set COMPRESS=as compressed backupset

REM Строка подключения Rman к базе
set CONSTRING=target /

REM строка подключения sqlplus
set CONSQL="/ as sysdba"

REM Местоположение Rman
set RMAN=%ORACLE_HOME%binrman

REM Местоположение SQLPLUS
set SQLPL=%ORACLE_HOME%binsqlplus

REM Временный файл
set TFILE=%TEMP%backup_%ORACLE_SID%.tmp


REM ---------------------------------------------

set ERR=0
set EXEC=%0 %1
if "%EXEC%"=="%0 " goto prov

if %1==t goto prov
if %1==a goto backarc
if %1==d goto delarc

echo alter system archive log current; > %TFILE%
echo select upper ('posled '),(max (SEQUENCE#)-5) from v$archived_log where DELETED='NO'; >> %TFILE%
echo exit >> %TFILE%

for /F "tokens=1,2 usebackq " %%1 in (`%SQLPL% %CONSQL% @%TFILE%`) do if %%1==POSLED set SEQN=%%2

IF %1==0 (
	move /Y %DEST%*.BK? %OLD%
	goto backdb
	)
IF %1==1 goto backdb


:prov
echo 1.Testing sqlplus connection
echo select 'POSLED ','Test_SQLPLUS_OK' from dual; > %TFILE%
echo exit >> %TFILE%
for /F "tokens=1,2 usebackq " %%1 in (`%SQLPL% %CONSQL% @%TFILE%`) do if %%1==POSLED set SEQN=%%2
echo Test Complete
echo 2.Testing write to destination dir
echo 2. Test write on destination dir OK > %DEST%test_file.txt
if ERRORLEVEL 1 ( 
	echo Write Error
	goto eof
	)
echo Test Complete
echo 3.Testing rman conection
echo backup format '%DEST%test_backup.bak' spfile;  > %TFILE%
%RMAN% %CONSTRING% @%TFILE%
echo Test Complete
echo Results:
echo 1. %SEQN%
type %DEST%test_file.txt
del /q /f %DEST%test_file.txt
if EXIST %DEST%test_backup.bak (
	echo 3. Testing rman OK
	del /q /f  %DEST%test_backup.bak
	) ELSE (
	echo 3. Test RMAN failed
	)

goto eof
:delarc
echo crosscheck archivelog all; > %TFILE%
echo delete FORCE NOPROMPT archivelog all; >> %TFILE%
%RMAN% %CONSTRING% @%TFILE%
echo ***********************************************************
echo ***      Do not forget to do FULL BACKUP OF THE DATABASE !!!    ***
echo ***********************************************************
goto eof

:backdb
echo run {  > %TFILE%
echo  sql 'alter system archive log current';  >> %TFILE%                                                                                                                           
echo  sql 'alter system checkpoint';   >> %TFILE%                                                                                                                                   
echo  allocate channel d1 type disk;  >> %TFILE%                                                                                                                                    
echo set limit channel d1 kbytes 4000000; >> %TFILE%
echo backup %COMPRESS% incremental level %1 skip inaccessible filesperset 1 format '%DEST%%%d_%%T_%%U.bkd' database include current controlfile;  >> %TFILE%                                            
echo sql 'alter system checkpoint';  >> %TFILE%                                                                                                                                    
echo sql 'alter system archive log current';  >> %TFILE%                                                                                                                           
echo backup %COMPRESS% filesperset 40 format '%DEST%%%d_%%T_%%U.bka' archivelog from sequence %SEQN% ;  >> %TFILE%                                                                                                  
echo backup format '%DEST%%%d_%%T_%%U.bkc' current controlfile;  >> %TFILE%                                                                                                          
echo backup format '%DEST%%%d_%%T_%%U.bks' spfile;  >> %TFILE%

echo }  >> %TFILE%

%RMAN% %CONSTRING% @%TFILE%
set /a ERR=%ERR%+%ERRORLEVEL%
:backarc

echo %COMPRESS%|findstr compressed
if ERRORLEVEL 1 (
echo alter system archive log current; > %TFILE%
echo set feedback off pagesize 0 heading off verify off linesize 200 trimspool off >> %TFILE%
echo spool %TFILE%.bat >> %TFILE%
echo select 'move /Y '^|^|name^|^|' %DEST%' from v$archived_log  where DEST_ID=1 and STATUS='A'; >> %TFILE%
echo spool off >> %TFILE%
echo exit >> %TFILE%
%SQLPL% %CONSQL% @%TFILE%

call %TFILE%.bat
set /a ERR=%ERR%+%ERRORLEVEL%

echo crosscheck backup; > %TFILE%
echo crosscheck archivelog all; >> %TFILE%
echo DELETE FORCE NOPROMPT EXPIRED backup; >> %TFILE%
%RMAN% %CONSTRING% @%TFILE%
) else (
echo crosscheck backup; > %TFILE%
echo crosscheck archivelog all; >> %TFILE%
echo DELETE FORCE NOPROMPT EXPIRED backup; >> %TFILE%
echo sql 'alter system checkpoint';  >> %TFILE%                                                                                                                                    
echo sql 'alter system archive log current';  >> %TFILE%                                                                                                                           
echo backup %COMPRESS% filesperset 40 format '%DEST%%%d_%%T_%%U_all.bka' archivelog all delete input;  >> %TFILE%                                                                                                  
echo backup format '%DEST%%%d_%%T_%%U.bkc' current controlfile;  >> %TFILE%                                                                                                          

%RMAN% %CONSTRING% @%TFILE%
)
set /a ERR=%ERR%+%ERRORLEVEL%
:eof
exit /b %ERR%

Спасибо за внимание.

Автор: cawaleb

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js