Standby database manuelle (cold) sur Windows - Std Edition (services et tâches planifiées)
De wikiGite
Sur Windows, l'automatisation du démarrage de la base standby et de l'application des archives est un peu plus compliquée que sous linux.
Ci-dessous, le serveur primaire sera SERVER1 et le secondaire SERVER2.
La base s'appellera ORCL.
Sommaire
Création des bases
sur SERVER1
Créer la base primaire avec les archivelogs activés, faire une sauvegarde à froid et générer un standby control file (Standby database manuelle (cold) sur Standard Edition), la transférer sur SERVER2.
sur SERVER2
Créer la base à l'identique. Arrêter ensuite la base et écraser les fichiers avec la sauvegarde venant de SERVER1. Les control files seront remplacés par le standby control file.
Modifier la clé de registre AUTOSTART
La standby ne doit pas démarrer en "OPEN" mais en "RECOVER". Il faut modifier son mode de démarrage automatique.
Lancer REGEDIT, trouver le registre :
HKLM/SOFTWARE/ORACLE/Key_Ora10gDB_home1
La clé a la forme ORA_{DB_NAME}_AUTOSTART (ici ORA_ORCL_AUTOSTART). Double-cliquer sur cette clé et la mettre à « FALSE ». Ne pas fermer REGEDIT, on en aura besoin plus tard.
Créer le service de lancement de la standby
Il faut maintenant créer un service spécifique qui lancera automatiquement la base Standby. Commencer par télécharger 2 utilitaires, INSTSRV et SRVANY. Ils se trouvent dans le kit de ressources techniques, ou bien ici :
http://www.inscripta.net/ressources/articl...tion/srvany.zip
Créer un service "OracleStandbyORCL" avec INSTSRV, service qui utilisera la commande SRVANY :
"C:\<répertoire utilitaires>\instsrv" OracleStandbyORCL "C:\<répertoire utilitaires>\srvany"
Vérifier dans le gestionnaire de service qu'il est bien créé.
Copier le code ci-dessous dans un fichier "ORCL.REG", EN REMPLACANT "ORACLE_SID" par le nom de la base ("ORCL" ici), l'utilisateur qui lancera le service, ainsi que le chemin du script qui lancera la base dans la clé Parameters :
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\OracleStandbyORACLE_SID] "Type"=dword:00000010 "Start"=dword:00000002 "ErrorControl"=dword:00000001 "ImagePath"=hex(2):45,00,3a,00,5c,00,6f,00,72,00,61,00,63,00,6c,00,65,00,5c,00,\ 70,00,72,00,6f,00,64,00,75,00,63,00,74,00,5c,00,31,00,30,00,2e,00,32,00,2e,\ 00,30,00,5c,00,64,00,62,00,5f,00,31,00,5c,00,42,00,49,00,4e,00,5c,00,73,00,\ 72,00,76,00,61,00,6e,00,79,00,2e,00,65,00,78,00,65,00,00,00 "DisplayName"="OracleStandbyORACLE_SID" "ObjectName"="Administrateur" "DependOnService"=hex(7):4f,00,72,00,61,00,63,00,6c,00,65,00,53,00,65,00,72,00,\ 76,00,69,00,63,00,65,00,4f,00,52,00,41,00,43,00,4c,00,45,00,5f,00,53,00,49,\ 00,44,00,00,00,00,00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\OracleStandbyORACLE_SID\Parameters] "AppDirectory"="\"C:\\<répertoire utilitaires>\"" "Application"="\"C:\\<répertoire utilitaires>\\start_standby.cmd\"" "AppParameters"="ORACLE_SID" [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\OracleStandbyORACLE_SID\Security] "Security"=hex:01,00,14,80,b8,00,00,00,c4,00,00,00,14,00,00,00,30,00,00,00,02,\ 00,1c,00,01,00,00,00,02,80,14,00,ff,01,0f,00,01,01,00,00,00,00,00,01,00,00,\ 00,00,02,00,88,00,06,00,00,00,00,00,14,00,fd,01,02,00,01,01,00,00,00,00,00,\ 05,12,00,00,00,00,00,18,00,ff,01,0f,00,01,02,00,00,00,00,00,05,20,00,00,00,\ 20,02,00,00,00,00,14,00,8d,01,02,00,01,01,00,00,00,00,00,05,04,00,00,00,00,\ 00,14,00,8d,01,02,00,01,01,00,00,00,00,00,05,06,00,00,00,00,00,14,00,00,01,\ 00,00,01,01,00,00,00,00,00,05,0b,00,00,00,00,00,18,00,fd,01,02,00,01,02,00,\ 00,00,00,00,05,20,00,00,00,23,02,00,00,01,01,00,00,00,00,00,05,12,00,00,00,\ 01,01,00,00,00,00,00,05,12,00,00,00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\OracleStandbyORACLE_SID\Enum] "0"="Root\\LEGACY_ORACLESTANDBYORACLE_SID\\0000" "Count"=dword:00000001 "NextInstance"=dword:00000001
Double-cliquer sur le fichier, accepter la modification des registres.
Retourner dans REGEDIT, trouver la clé HKLM\SYSTEM\CurrentControlSet\Services\OracleStandbyORCL nouvellement créée. Modifier à droite la valeur "DependOnService" en double-cliquant dessus, par "OracleServiceORCL" (la clé est en Héxa dans le fichier texte ci-dessus et ne peut être modifiée qu'à posteriori).
Note : on voit dans la clé "OracleStandbyORCL" que c'est SRVANY qui est lancé, avec les paramètres de la sous-clé "Parameters" (nom du script de démarrage de la base et SID de la base à passer à ce script)
Supprimer la clé "Enum" à gauche, elle sera recréée par PnP avec une valeur correcte "LEGACYxxx" la première fois qu'on entrera dans les propriétés du service.
Quitter REGEDIT, et dans le gestionnaire de services afficher les propriétés de OracleStandbyORCL pour créer la clé Enum, en profiter pour vérifier les paramètres.
Stopper le service OracleServiceORCL s'il ne l'est pas déjà. Lancer le service OracleStandbyORCL, vérifier qu'il se lance sans erreur et qu'il relance bien le service OracleServiceORCL.
Lancer sqlplus en SYSDBA, et vérifier que la base est bien en mode STANDBY :
C:\> set ORACLE_SID=ORCL C:\> sqlplus / as sysdba SQL> select instance_name, status from v$instance; INSTANCE_NAME STATUS ---------------- --------------- ORCL MOUNTED SQL> select database_role from v$database; DATABASE_ROLE ---------------- PHYSICAL STANDBY
Modifier tout de suite le paramètre d'initialisation standby_file_management (sa valeur par défaut ne permet pas la re-création de tablespaces et de fichiers de données sur la standby lorsqu'ils sont créés sur la base primaire) :
alter system set standby_file_management=AUTO;
Synchronisation des bases
sur SERVER1
Planifier une tâche de synchronisation des archivelogs entre les 2 serveurs
Le script "synchro_standby.cmd" utilise BLAT pour envoyer des mails d'alertes (Blat est téléchargeable sur http://www.blat.net) et lance d'autres scripts .cmd et .sql détaillés plus bas. Planifier ce script à intervalles réguliers, par exemple tous les 1/4 d'heures : ce sera la valeur maximale de décalage entre la base primaire et la base standby.
@echo off :: Primary to Standby server synchronization :: (copy Oracle archivelogs to the Standby server) setlocal enableExtensions enableDelayedExpansion :: ====================== :: replication parameters :: ====================== SET ORACLE_SID=%1 SET _SOURCE_DIR=/cygdrive/c/oradata/%ORACLE_SID%/archives/ SET _DESTINATION_SERVER=SERVER2 SET _DESTINATION_DIR=archivestandby%ORACLE_SID% SET _SCRIPTS_DIR=C:\<répertoire utilitaires>\synchro_standby SET _LOG_DIR=%_SCRIPTS_DIR%\log SET _SQLPLUS=C:\oracle\product\10.2.0\db_1\BIN\sqlplus.exe -L :: ============================= :: mail notifications parameters :: ============================= SET _MAIL_RESSOURCES_DIR=C:\<répertoire utilitaires>\mail_ressources SET _MAIL_SERVER_INI=%_MAIL_RESSOURCES_DIR%\mail_server.ini SET _MAIL_ADMINS_INI=%_MAIL_RESSOURCES_DIR%\mail_admins.ini SET _MAIL_FROM_INI=%_MAIL_RESSOURCES_DIR%\mail_from.ini SET _BLAT=%_MAIL_RESSOURCES_DIR%\blat.exe :: construct prefix for log file with date and time set _DATE_STR= set _TIME_STR= for /f "tokens=1-3 delims=/.- " %%a in ("%DATE:* =%") do set _DATE_STR=%%a-%%b-%%c for /f "tokens=1-3 delims=:," %%a in ("%TIME:* =%") do set _TIME_STR=%%a.%%b.%%c SET _LOGFILE=%_DATE_STR%_%_TIME_STR%_%ORACLE_SID%_%~n0.log :: timestamp for the log file date /t > %_LOG_DIR%\%_LOGFILE% 2>&1 time /t >> %_LOG_DIR%\%_LOGFILE% 2>&1 :: test if parameters are initialized IF "%ORACLE_SID%" == "" ( call :send_error_notification_to_admins "ERROR : %ORACLE_SID% Synchronization Problem" "script %~n0 : Parameter ORACLE_SID not initialized" >> %_LOG_DIR%\%_LOGFILE% 2>&1 goto END ) :: Switch archive log file to copy last information to the Standby server %_SQLPLUS% /nolog @%_SCRIPTS_DIR%\switchlog.sql >> %_LOG_DIR%\%_LOGFILE% 2>&1 IF NOT "%ERRORLEVEL%"=="0" ( call :send_error_notification_to_admins "ERROR : %ORACLE_SID% Switch archive log Problem" "script %~n0 : Problem during switching archive log" "%_LOG_DIR%\%_LOGFILE%" >> %_LOG_DIR%\%_LOGFILE% 2>&1 goto END ) :: Synchronize archives to the Standby server CALL %_SCRIPTS_DIR%\cwrsync.cmd %_SOURCE_DIR% %_DESTINATION_SERVER% %_DESTINATION_DIR% >> %_LOG_DIR%\%_LOGFILE% 2>&1 IF NOT "%ERRORLEVEL%"=="0" ( call :send_error_notification_to_admins "ERROR : %ORACLE_SID% Synchronization Problem" "script %~n0 : Synchronization problem between Primary and Standby Server" "%_LOG_DIR%\%_LOGFILE%" >> %_LOG_DIR%\%_LOGFILE% 2>&1 ) :END endlocal goto :eof :: =============================== :send_error_notification_to_admins :: =============================== :: Send an error notification to administrators :: Parameters: :: %1=subject :: %2=body :: %3=logfile (not required) :: %4=logfile (not required) SET _MAIL_SERVER= FOR /F "eol=#" %%c in ('type %_MAIL_SERVER_INI%') do ( SET _MAIL_SERVER=%%c ) SET _MAIL_FROM= FOR /F "eol=#" %%c in ('type %_MAIL_FROM_INI%') do ( SET _MAIL_FROM=%%c ) SET _MAIL_TO_ADMINS= FOR /F "eol=#" %%c in ('type %_MAIL_ADMINS_INI%') do ( IF "!_MAIL_TO_ADMINS!" == "" ( SET _MAIL_TO_ADMINS=%%c ) else ( SET _MAIL_TO_ADMINS=!_MAIL_TO_ADMINS!,%%c ) ) SET _BLAT_PARAMETERS=-body %2 -server %_MAIL_SERVER% -f %_MAIL_FROM% -t %_MAIL_TO_ADMINS% -subject %1 IF NOT "%3" == "" ( SET _BLAT_PARAMETERS=%_BLAT_PARAMETERS% -attach %3 ) IF NOT "%4" == "" ( SET _BLAT_PARAMETERS=%_BLAT_PARAMETERS% -attach %4 ) call %_BLAT% %_BLAT_PARAMETERS% goto :eof
Il lance un premier script SQL "switchlog.sql' qui force un switch d'archivelog :
connect / as sysdba alter system switch logfile; exit
puis il lance un script DOS qui utilise CWRSYNC (http://sourceforge.net/projects/sereds/files/cwRsync/, portage CygWin de l'utilitaire RSYNC connu sous linux). RSYNC permet de synchroniser les répertoires d'archivelogs des deux serveurs en incrémental, sans devoir renvoyer tous les fichiers à chaque fois.
Il s'installe
- En tant que serveur sur SERVER2. Il crée un service qui lui permet de fonctionner en tâche de fond, et d'attendre les requêtes de SERVER1
- En tant que client sur SERVER1, qui enverra ses archivelogs vers SERVER2 par ce biais
Sur SERVER1, le script cwrsync.cmd est fourni lors de l'installation de CWRSYNC (dans le répertoire de celui-ci) à titre d'exemple. Il suffit de reprendre ce script, de vérifier les valeurs des variables au début, et d'ajouter à la fin du fichier :
SET _REP_SOURCE=%1 SET _SERV_DEST=%2 SET _REP_DEST=%3 rsync -arvz --delete %_REP_SOURCE% %_SERV_DEST%::%_REP_DEST%
Les 3 paramètres lui seront passés par synchro_standby.cmd.
Paramétrer aussi les fichiers de configuration de Blat, dans C:\<répertoire utilitaires>\mail_ressources. Les .INI sont des fichiers texte, avec une valeur par ligne (respectivement nom du serveur SMTP, nom des destinataires des mails et nom de l'expéditeur).
sur SERVER2
Installer également CWRSYNC, en mode serveur. Editer le fichier rsyncd.conf dans le répertoire d'installation pour créer un point de partage :
use chroot = false strict modes = false hosts allow = * log file = rsyncd.log pid file = rsyncd.pid [ArchiveStandbyORCL] path = C:\oradata\ORCL\archives_temp read_only = false
Relancer le service "RsyncServer" pour prendre en compte les modifications. NOTE : créer le répertoire C:\oradata\ORCL\archives_temp, qui recevra les archives de SERVER1. Ce répertoire reçoit temporairement les archivelogs, avant de les copier dans le "vrais" répertoire d'archive de la base et de les appliquer. On a ainsi, en cas d'erreur, une sauvegarde des archives. Ce répertoire étant synchronisé avec celui des archives de SERVER1, il suffit de faire un backup RMAN sur SERVER1 avec sauvegarde + suppression des archivelogs. Le vidage du répertoire sur SERVER1 videra automatiquement celui de SERVER2 à la synchronisation suivante.
Le script "apply_archive.cmd" applique les archivelogs dans la base standby. Il utilise lui aussi BLAT ainsi qu'un script SQL :
@echo off :: Apply archives from Primary server in the Standby database setlocal enableExtensions enableDelayedExpansion :: ====================== :: replication parameters :: ====================== SET ORACLE_SID=%1 SET _LASTARCHIVE=%2 SET _SCRIPTS_DIR=C:\<répertoire utilitaires>\apply_archive SET _LOG_DIR=%_SCRIPTS_DIR%\log SET _ARCHIVE_FROM_PRIMARY_DIR=C:\oradata\%ORACLE_SID%\archives_temp SET _ARCHIVE_TO_APPLY_DIR=C:\oradata\%ORACLE_SID%\archives SET _SQLPLUS=C:\oracle\product\10.2.0\db_1\BIN\sqlplus.exe -L :: ============================= :: mail notifications parameters :: ============================= SET _MAIL_RESSOURCES_DIR=C:\<répertoire utilitaires>\mail_ressources SET _MAIL_SERVER_INI=%_MAIL_RESSOURCES_DIR%\mail_server.ini SET _MAIL_ADMINS_INI=%_MAIL_RESSOURCES_DIR%\mail_admins.ini SET _MAIL_FROM_INI=%_MAIL_RESSOURCES_DIR%\mail_from.ini SET _BLAT=%_MAIL_RESSOURCES_DIR%\blat.exe :: construct prefix for log file with date and time set _DATE_STR= set _TIME_STR= for /f "tokens=1-3 delims=/.- " %%a in ("%DATE:* =%") do set _DATE_STR=%%a-%%b-%%c for /f "tokens=1-3 delims=:," %%a in ("%TIME:* =%") do set _TIME_STR=%%a.%%b.%%c SET _LOGFILE=%_DATE_STR%_%_TIME_STR%_%ORACLE_SID%_%~n0.log :: timestamp for the log file date /t > %_LOG_DIR%\%_LOGFILE% 2>&1 time /t >> %_LOG_DIR%\%_LOGFILE% 2>&1 :: apply archive from Primary server to Standby %_SQLPLUS% /nolog @%_SCRIPTS_DIR%\apply_archive.sql >> %_LOG_DIR%\%_LOGFILE% 2>&1 IF NOT "!ERRORLEVEL!"=="0" ( call :send_error_notification_to_admins "ERROR : %ORACLE_SID% Synchronization Problem" "script %~n0 : Error in launching applying archives: SQL Plus Problem" "%_LOG_DIR%\%_LOGFILE%" >> %_LOG_DIR%\%_LOGFILE% 2>&1 goto END ) :: extract waited archive file name from Log (ORA-00308) SET _NEXTARCHIVE= for /F "tokens=5 delims='\" %%a IN ('findstr /r /i /c:"ORA-00308" %_LOG_DIR%\%_LOGFILE%') do set _NEXTARCHIVE=%%a echo Next Archive : %_NEXTARCHIVE% >> %_LOG_DIR%\%_LOGFILE% 2>&1 :: if file header is corrupted, ORA-00308 is not logged in the log file and no file name is provided :: if the script cannot connect to the database and no file name is provided IF "%_NEXTARCHIVE%" == "" ( call :send_error_notification_to_admins "ERROR : %ORACLE_SID% Synchronization Problem" "script %~n0 : Error in applying %_LASTARCHIVE% : File Header Problem OR Database Access Problem" "%_LOG_DIR%\%_LOGFILE%" >> %_LOG_DIR%\%_LOGFILE% 2>&1 goto END ) :: if file is corrupted, the apply fails and the file name waited by standby database is always the same IF "%_NEXTARCHIVE%" == "%_LASTARCHIVE%" ( call :send_error_notification_to_admins "ERROR : %ORACLE_SID% Synchronization Problem" "script %~n0 : Error in applying %_NEXTARCHIVE% : File Corrupted" "%_LOG_DIR%\%_LOGFILE%" >> %_LOG_DIR%\%_LOGFILE% 2>&1 goto END ) :: copy the new archive logs and apply them into the Standy Database IF EXIST %_ARCHIVE_FROM_PRIMARY_DIR%\%_NEXTARCHIVE% ( :: get archive file sended by primary server copy /Y %_ARCHIVE_FROM_PRIMARY_DIR%\%_NEXTARCHIVE% %_ARCHIVE_TO_APPLY_DIR% >> %_LOG_DIR%\%_LOGFILE% 2>&1 :: call script recursively to apply archive log echo === RECURSIVE CALL, AT LEAST ONE ARCHIVELOG === >> %_LOG_DIR%\%_LOGFILE% 2>&1 %_SCRIPTS_DIR%\apply_primary_archive.cmd %ORACLE_SID% %_NEXTARCHIVE% :: delete the applyed archivelog del /F /Q %_ARCHIVE_TO_APPLY_DIR%\%_NEXTARCHIVE% >> %_LOG_DIR%\%_LOGFILE% 2>&1 ) :END endlocal goto :eof :: =============================== :send_error_noticication_to_admins :: =============================== :: Send an error notification to administrators :: Parameters: :: %1=subject :: %2=body :: %3=logfile (not required) :: %4=logfile (not required) SET _MAIL_SERVER= FOR /F "eol=#" %%c in ('type %_MAIL_SERVER_INI%') do ( SET _MAIL_SERVER=%%c ) SET _MAIL_FROM= FOR /F "eol=#" %%c in ('type %_MAIL_FROM_INI%') do ( SET _MAIL_FROM=%%c ) SET _MAIL_TO_ADMINS= FOR /F "eol=#" %%c in ('type %_MAIL_ADMINS_INI%') do ( IF "!_MAIL_TO_ADMINS!" == "" ( SET _MAIL_TO_ADMINS=%%c ) else ( SET _MAIL_TO_ADMINS=!_MAIL_TO_ADMINS!,%%c ) ) SET _BLAT_PARAMETERS=-body %2 -server %_MAIL_SERVER% -f %_MAIL_FROM% -t %_MAIL_TO_ADMINS% -subject %1 IF NOT "%3" == "" ( SET _BLAT_PARAMETERS=%_BLAT_PARAMETERS% -attach %3 ) IF NOT "%4" == "" ( SET _BLAT_PARAMETERS=%_BLAT_PARAMETERS% -attach %4 ) call %_BLAT% %_BLAT_PARAMETERS% goto :eof
Il lance le script SQL "apply_archive.sql" :
connect / as sysdba alter database recover automatic standby database; exit
Paramétrer aussi les fichiers de configuration de Blat, dans C:\<répertoire utilitaires>\mail_ressources. Les .INI sont des fichiers texte, avec une valeur par ligne (respectivement nom du serveur SMTP, nom des destinataires des mails et nom de l'expéditeur).
TESTS
Sur SERVER1, lancer la tâche planifiée "synchro_standby", qui doit générer une archive et copier celle-ci sur SERVER2 sous archives_temp Sur SERVER2, lancer la tâche planifiée "apply_archive", qui doit intégrer l'archive. Vérifier les log du script, qui doivent ressembler à ceci :
12/08/2008 16:56 SQL*Plus: Release 10.2.0.4.0 - Production on Tue Aug 12 16:56:04 2008 Copyright (c) 1982, 2007, Oracle. All Rights Reserved. Connected. alter database recover automatic standby database * ERROR at line 1: ORA-00279: change 50345552 generated at 08/12/2008 16:51:03 needed for thread 1 ORA-00289: suggestion : F:\E2TSW\ARCHIVES\ARC00162_0662457568.001 ORA-00280: change 50345552 for thread 1 is in sequence #162 ORA-00278: log file 'F:\E2TSW\ARCHIVES\ARC00162_0662457568.001' no longer needed for this recovery ORA-00308: cannot open archived log 'F:\E2TSW\ARCHIVES\ARC00162_0662457568.001' ORA-27041: unable to open file OSD-04002: unable to open file O/S-Error: (OS 2) The system cannot find the file specified. Disconnected from Oracle Database 10g Release 10.2.0.4.0 - Production Next Archive : ARC00162_0662457568.001
Les messages d'erreur sont "normaux". Le numéro d'archive indiqué sur l'ORA-00278 et à la fin du log soit être supérieur de 1 par rapport aux archiveslogs existants dans archive_temp : c'est la prochaine archive attendue de SERVER1.