Oracle Dataguard 11G Part #1 : Mise en place d’un Physical Dataguard

Après quelques temps d’inactivité, j’ai décidé de faire une série d’articles sur la technologie Oracle Dataguard 11G, afin de présenter les principales caractéristiques et la mise en place de ce mode de disponibilité.

Dans ces articles, nous verrons (dans l’ordre) :

Oracle Dataguard 11G Part #1 : Mise en place d’un Physical Dataguard
Oracle Dataguard 11G Part #2 : Comment changer le mode de protection de Dataguard ?
Oracle Dataguard 11G Part #3 : Gestion et supervision : Oracle Dataguard BROKER
Oracle Dataguard 11G Part #4 : Mise en place d’ACTIVE DATAGUARD
Oracle Dataguard 11G Part #5 : Mise en place d’un LOGICAL DATAGUARD
Oracle Dataguard 11G Part #6 : Restauration Rman d’une base Primaire : Les impacts

Bon, mais qu’est ce qu’un environnement DATAGUARD et à quoi cela peut il servir ?

Et bien c’est assez simple en fait. Un environnement Oracle DATAGUARD est un environnement pourvu d’une base de données dite principale (ou primary pour les intimes), et d’une base de secours sur un autre serveur (idéalement un autre datacenter / site) alimentée en temps rêel à partir des archivelogs de la base principale. Le mécanisme est entièrement automatique, y compris sa supervision.

Globalement, dans la plupart des cas de configuration, cette base de données de secours (standby pour les intimes) pourra être activée dès lors où la base de données principale ne sera plus opérationnelle, ou accessible. On nomme cela un PHYSICAL DATAGUARD. Cela permet d’avoir une continuité des opérations, qui seront redigirées vers le serveur et donc la base dite de secours / Standby.
Dans d’autres cas, plus rares de part mon expérience, cette base de données de secours pourra également être utilisée en parallèle de la base de données principale à des fins de tests, de récupération d’informations, de réglages ou autres. On nomme cela un LOGICAL DATAGUARD. Dans cette configuration, et à la différence de l’autre configuration PHYSICAL, cette base de secours est OPEN, alors que dans l’autre mode, elle serait uniquement MOUNTED en mode STANDBY (pour permettre l’application des archivelogs).

Vous l’avez compris, dans tous les cas, nous avons la notion d’archivelogs, lequels permettent d’alimenter la base de secours, qu’elle soit dans un mode PHYSICAL ou LOGICAL. Sans ce mode archivelog, il faut oublier tout mécanisme de disponibilité DATAGUARD, ou encore MANUAL Stanby

Pour la différence entre un environnement de secours DATAGUARD et MANUAL Standby, c’est simple également car d’un coté tout est géré par la mécanique dataguard Oracle (envoi d’archivelogs, application sur la base de secours, supervision via DGMGMRL) et de l’autre tout est à faire manuellement via pack de scripts OS / SQL.

Le petit plus de Dataguard, c’est du temps reel, alors qu’avec une configuration « Manual standby », cela sera lié à la planification qui sera mise en place pour l’envoie des archivelogs et leur application sur la base de secours.

D’un coté, une base de secours sera activée avec la dernière transaction datant d’avant panne / crash, de l’autre la base de secours sera activée avec une dernière transaction datant de la dernière application des archivelogs. Nous ne sommes donc pas, en mode Manual standby, en temps reel.

Evidemment, comme toute fonctionnalité « non défaut », Dataguard nécessite un licensing spécifique. Le fonctionnement DATAGUARD n’est disponible qu’en ENTERPRISE EDITION, et est une option supplémentaire payante.

Bon, passons maintenant à la partie technique. Je vais ici détailler la mise en place d’un PHYSICAL DATAGUARD

Le contexte technique, sur lequel je me base pour démarrer ce tuto, est le suivant :

  • 2 serveurs (VM) Oracle Linux 6 installés et configurés (accès réseau et autres), disposant de 60Go d’espace chacun (à adapter en fonction du contexte d’étude)
  • Moteurs oracle 11GR2 enterprise edition installés sur les deux serveurs
  • Base de données « primaire » UP sur le premier serveur, en mode Archivelog, nommée ici « MICKPRIM »
  • Listener Oracle UP sur les deux serveurs, en configuration statique :

Exemple pour le serveur « primaire » :

SID_LIST_LISTENER =
 (SID_LIST =
 (SID_DESC =
 (ORACLE_HOME = /oracle/product/11.2.0.4)
 (SID_NAME = MICKPRIM)
 ) )
LISTENER =
 (DESCRIPTION =
 (ADDRESS = (PROTOCOL = TCP)(HOST = srvoraprim)(PORT = 1521))
 )
ADR_BASE_LISTENER = /oracle

Exemple pour le serveur « secondaire / secours »

SID_LIST_LISTENER =
 (SID_LIST =
 (SID_DESC =
 (ORACLE_HOME = /oracle/product/11.2.0.4)
 (SID_NAME = MICKSTBY)
 ) )
LISTENER =
 (DESCRIPTION =
 (ADDRESS = (PROTOCOL = TCP)(HOST = srvorastby)(PORT = 1521))
 )
ADR_BASE_LISTENER = /oracle

 

Mais avant de démarrer d’emblée les actions, que représente un PHYSICAL DATAGUARD ?

Un Physical dataguard se base sur une base de données Standby (de secours) dont la structure est identique à la base de données Primary (principale).
Les archivelogs générées par la base primary seront directement appliquées sur la base standby.
Cette solution technique est couramment choisie. Elle permet notamment d’assurer une protection maximale en cas de crash de la base primaire.

Pour construire la base de secours « STANDBY », nous pourrons donc utiliser aisément notre ami RMAN, qui permet de réaliser (depuis la version 9i) un duplicate for standby, et plus particulièrement en 11G un duplicate for standby from active database.

Et oui, en 11g, grosse nouveauté (qui date un peu maintenant..) puisque nous pouvons construire une standby database à partir d’une base de données directement, au lieu d’utiliser un dernier backup rman (versions antérieures).

Je ne parlerais pas des versions 8i sur lesquelles j’ai eu à mettre en place un Physical dataguard dans une vie passée, c’était quelque peu moins efficace et rapide, et demandait pas mal de code et d’actions, mais le principe de fonctionnement et paramétrage reste globalement le même.

Mais avant la création de cette instance STANDBY, il faut préparer le terrain sur la base de données PRIMARY.

Première étape, très importante et obligatoire à toute configuration Standby, on s’assure que la base primary soit bien en force logging (ce qui sous entend de forcer la génération d’archivelog, même s’il y a des objets en Nologging)

SQL> select NAME,LOG_MODE,OPEN_MODE,DATABASE_ROLE,FORCE_LOGGING,DATAGUARD_BROKER,GUARD_STATUS,PROTECTION_MODE from v$database;

NAME LOG_MODE OPEN_MODE DATABASE_ROLE FOR DATAGUAR GUARD_S PROTECTION_MODE
--------- ------------ -------------------- ---------------- --- -------- ------- --------------------
MICKPRIM ARCHIVELOG READ WRITE PRIMARY NO DISABLED NONE MAXIMUM PERFORMANCE

=> Activation du Force Logging :

SQL> shutdown immediate ;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount ;
ORACLE instance started.

Total System Global Area 1068937216 bytes
Fixed Size 2260088 bytes
Variable Size 671089544 bytes
Database Buffers 390070272 bytes
Redo Buffers 5517312 bytes
Database mounted.
SQL> alter database force logging ;

Database altered.

SQL> alter database open;

Database altered.

SQL> select NAME,LOG_MODE,OPEN_MODE,DATABASE_ROLE,FORCE_LOGGING,DATAGUARD_BROKER,GUARD_STATUS,PROTECTION_MODE from v$database;

NAME LOG_MODE OPEN_MODE DATABASE_ROLE FOR DATAGUAR GUARD_S PROTECTION_MODE
--------- ------------ -------------------- ---------------- --- -------- ------- --------------------
MICKPRIM ARCHIVELOG READ WRITE PRIMARY YES DISABLED NONE MAXIMUM PERFORMANCE

SQL> select force_logging from v$database;

FORCE_LOGGING
---
YES

Ensuite, on vérifie que la base utilise bien un fichier de mot de passe et que le paramètre « REMOTE_LOGIN_PASSWORDFILE » soit bien à « EXCLUSIVE » :

SQL>show parameter remote_login_passwordfile

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
remote_login_passwordfile string EXCLUSIVE

[oracle@srvoraprim dbs]$ ls -l orapw*
-rw-r-----. 1 oracle dba 1536 Nov 7 10:46 orapwMICKPRIM

On vérifie le db_name et db_unique_name  de notre base :

SQL> sho parameter _name

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_name string MICKPRIM
db_unique_name string MICKPRIM

Dans mon cas, les 2 paramètres sont identiques. Sur la base Standby, le DB_NAME sera le même que la base primaire (ie MICKPRIM), mais la valeur de db_unique_name devra être différente (MICKSTBY).

De plus, la valeur de ce paramètre db_unique_name devra être indiquée dans la configuration dataguard « DG_CONFIG », pour les 2 bases. (cf plus bas où la configuration est indiquée).

On prépare maintenant les alias TNS qui seront utilisés aussi bien par RMAN (pour la mise en place de la database en Standby) que pour la fonctionnalité Dataguard.

Exemple :

MICKPRIM =
(DESCRIPTION =
 (ADDRESS_LIST =
 (ADDRESS = (PROTOCOL = TCP)(HOST = srvoraprim)(PORT = 1521))
 )
 (CONNECT_DATA =
 (SERVICE_NAME = MICKPRIM)(UR=A)
 )
)

MICKSTBY =
(DESCRIPTION =
 (ADDRESS_LIST =
 (ADDRESS = (PROTOCOL = TCP)(HOST = srvorastby)(PORT = 1521))
 )
 (CONNECT_DATA =
 (SERVICE_NAME = MICKSTBY)(UR=A)
 )
)

Bien sur, ce tnsnames devra être en place sur les 2 serveurs.

On vérifie ensuite que le TNSPING fonctionne bien entre les serveurs. Si cela ne passe pas, vérifier votre firewall et le service « iptables » (« service iptables status » à lancer en ROOT)

-> Sur le serveur dit primaire :

[oracle@srvoraprim ~]$ tnsping MICKSTBY

TNS Ping Utility for Linux: Version 11.2.0.4.0 - Production on 07-NOV-2016 14:49:40

Copyright (c) 1997, 2013, Oracle. All rights reserved.

Used parameter files:

Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = srvorastby)(PORT = 1521))) (CONNECT_DATA = (SERVICE_NAME = MICKSTBY)(UR=A)))
OK (30 msec)

-> Sur le serveur secondaire

[oracle@srvorastby ~]$ tnsping MICKPRIM

TNS Ping Utility for Linux: Version 11.2.0.4.0 - Production on 07-NOV-2016 14:49:52

Copyright (c) 1997, 2013, Oracle. All rights reserved.

Used parameter files:

Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = srvoraprim)(PORT = 1521))) (CONNECT_DATA = (SERVICE_NAME = MICKPRIM)(UR=A)))
OK (0 msec)

On passe maintenant à la configuration de Dataguard en lui même, sur l’instance Oracle PRIMAIRE.

Déjà, on sauvegarde le fichier de paramètre actuellement utilisé au cas où, puis on ajoute les paramètres liés à Dataguard qui sont :

LOG_ARCHIVE_CONFIG='DG_CONFIG=(MICKPRIM,MICKSTBY)'
LOG_ARCHIVE_DEST_1='location=/oradata/MICKPRIM/arch valid_for=(all_logfiles,all_roles) db_unique_name=MICKPRIM'
LOG_ARCHIVE_DEST_2='SERVICE=MICKSTBY NOAFFIRM ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=MICKSTBY'
LOG_ARCHIVE_DEST_STATE_2=ENABLE
LOG_ARCHIVE_MAX_PROCESSES=30
FAL_SERVER=MICKSTBY
FAL_CLIENT=MICKPRIM
STANDBY_FILE_MANAGEMENT=AUTO

Les 2 paramètres FAL_SERVER et FAL_CLIENT, configurés sur les 2 instances, serviront à réaliser des switchovers entre les bases (la base primaire devient standby, et vice versa).

Le paramètre STANDBY_FILE_MANAGEMENT quant à lui permet la gestion automatique des fichiers de base de données (datafiles). Autrement dit, si un datafile est crée / ajouté sur la base primaire, il sera automatiquement crée / ajouté sur l’instance standby.

Attention, ce paramètre ne peut être positionné en AUTO que lors d’une configuration DATAGUARD en tant que tel (donc enterprise edition + option..)

En ce qui concerne les 2 paramètres FAL_SERVER & FAL_CLIENT, iI n’est pas obligatoire de les indiquer pour le fonctionnement de dataguard, mais je le préconise cependant, le switchover pouvant s’avérer très utile en production.

Ce qui donne dans mon cas d’exmple:

*.audit_file_dest='/oracle/admin/MICKPRIM/adump'
*.audit_trail='db'
*.compatible='11.2.0.4.0'
*.control_files='/oradata/MICKPRIM/control01.ctl','/oradata/MICKPRIM/control02.ctl'
*.db_block_size=8192
*.db_domain=''
*.db_name='MICKPRIM'
*.diagnostic_dest='/oracle'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=MICKPRIMXDB)'
*.LOG_ARCHIVE_CONFIG='DG_CONFIG=(MICKPRIM,MICKSTBY)'
*.LOG_ARCHIVE_DEST_1='location=/oradata/MICKPRIM/arch valid_for=(all_logfiles,all_roles) db_unique_name=MICKPRIM'
*.LOG_ARCHIVE_DEST_2='SERVICE=MICKSTBY NOAFFIRM ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=MICKSTBY'
*.LOG_ARCHIVE_DEST_STATE_2=ENABLE
*.LOG_ARCHIVE_MAX_PROCESSES=30
*.FAL_SERVER=MICKSTBY
*.FAL_CLIENT=MICKPRIM
*.STANDBY_FILE_MANAGEMENT=AUTO
*.log_archive_format='%t_%s_%r.arc'
*.memory_target=1073741824
*.open_cursors=300
*.processes=150
*.remote_login_passwordfile='EXCLUSIVE'
*.undo_tablespace='UNDOTBS1'

Une fois cette partie de configuration terminée, nous allons passer à la mise en place de la base Standby nommée MICKSTBY, via RMAN.

Pour cela, copier tout d’abord le fichier de mot de passe « orapw » sur le serveur de secours.

[oracle@srvoraprim dbs]$ scp orapwMICKPRIM oracle@srvorastby:/oracle/product/11.2.0.4/dbs/orapwMICKSTBY
orapwMICKSTBY 100% 1536 1.5KB/s 00:00

Se connecter sur le serveur de secours, et creer ensuite un fichier d’initialisation oracle init.ora pour la base standby, contenant uniquement le nom de la base :

[oracle@srvorastby dbs]$ echo "db_name=MICKSTBY" > $ORACLE_HOME/dbs/initMICKSTBY.ora

Par la suite, il est désormais possible de démarrer l’instance oracle avant la duplication RMAN.

=> Notez bien que je vais gérer via RMAN les modifications liées au SPFILE.

[oracle@srvorastby ~]$ rman

Recovery Manager: Release 11.2.0.4.0 - Production on Mon Nov 7 14:52:47 2016

Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.

RMAN> connect target sys/oracle@MICKPRIM

connected to target database: MICKPRIM (DBID=2500540110)

RMAN> connect auxiliary sys/oracle@MICKSTBY

connected to auxiliary database (not started)

RMAN> startup clone nomount ;

RMAN>run {

allocate channel c1 device type disk;
allocate auxiliary channel c2 device type disk;
duplicate target database for standby from active database
 SPFILE
 set audit_file_dest='/oracle/admin/MICKSTBY/adump'
 set control_files='/oradata/MICKSTBY/control01.ctl'
 set fal_server='MICKPRIM'
 set fal_client='MICKSTBY'
 set standby_file_management='AUTO'
 set db_file_name_convert='/oradata/MICKPRIM','/oradata/MICKSTBY'
 set log_file_name_convert='/oradata/MICKPRIM','/oradata/MICKSTBY'
 set log_archive_dest_1='location=/oradata/MICKSTBY/arch valid_for=(all_logfiles,all_roles) db_unique_name=MICKSTBY'
 set log_archive_dest_2='service=MICKPRIM valid_for=(online_logfiles,primary_role) db_unique_name=MICKPRIM'
 set log_archive_dest_state_1='enable'
 set log_archive_dest_state_2='defer'
 set db_unique_name='MICKSTBY';
 }
 
using target database control file instead of recovery catalog
allocated channel: c1
channel c1: SID=46 device type=DISK

allocated channel: c2
channel c2: SID=171 device type=DISK

Starting Duplicate Db at 08-NOV-16

contents of Memory Script:
{
 backup as copy reuse
 targetfile '/oracle/product/11.2.0.4/dbs/orapwMICKPRIM' auxiliary format
 '/oracle/product/11.2.0.4/dbs/orapwMICKSTBY' targetfile
 '/oracle/product/11.2.0.4/dbs/spfileMICKPRIM.ora' auxiliary format
 '/oracle/product/11.2.0.4/dbs/spfileMICKSTBY.ora' ;
 sql clone "alter system set spfile= ''/oracle/product/11.2.0.4/dbs/spfileMICKSTBY.ora''";
}
executing Memory Script

Starting backup at 08-NOV-16
Finished backup at 08-NOV-16

sql statement: alter system set spfile= ''/oracle/product/11.2.0.4/dbs/spfileMICKSTBY.ora''

contents of Memory Script:
{
 sql clone "alter system set audit_file_dest =
 ''/oracle/admin/MICKSTBY/adump'' comment=
 '''' scope=spfile";
 sql clone "alter system set control_files =
 ''/oradata/MICKSTBY/control01.ctl'' comment=
 '''' scope=spfile";
 sql clone "alter system set fal_server =
 ''MICKPRIM'' comment=
 '''' scope=spfile";
 sql clone "alter system set fal_client =
 ''MICKSTBY'' comment=
 '''' scope=spfile";
 sql clone "alter system set standby_file_management =
 ''AUTO'' comment=
 '''' scope=spfile";
 sql clone "alter system set db_file_name_convert =
 ''/oradata/MICKPRIM'', ''/oradata/MICKSTBY'' comment=
 '''' scope=spfile";
 sql clone "alter system set log_file_name_convert =
 ''/oradata/MICKPRIM'', ''/oradata/MICKSTBY'' comment=
 '''' scope=spfile";
 sql clone "alter system set log_archive_dest_1 =
 ''location=/oradata/MICKSTBY/arch valid_for=(all_logfiles,all_roles) db_unique_name=MICKSTBY'' comment=
 '''' scope=spfile";
 sql clone "alter system set log_archive_dest_2 =
 ''service=MICKPRIM valid_for=(online_logfiles,primary_role) db_unique_name=MICKPRIM'' comment=
 '''' scope=spfile";
 sql clone "alter system set log_archive_dest_state_1 =
 ''enable'' comment=
 '''' scope=spfile";
 sql clone "alter system set log_archive_dest_state_2 =
 ''defer'' comment=
 '''' scope=spfile";
 sql clone "alter system set db_unique_name =
 ''MICKSTBY'' comment=
 '''' scope=spfile";
 shutdown clone immediate;
 startup clone nomount;
}
executing Memory Script

sql statement: alter system set audit_file_dest = ''/oracle/admin/MICKSTBY/adump'' comment= '''' scope=spfile

sql statement: alter system set control_files = ''/oradata/MICKSTBY/control01.ctl'' comment= '''' scope=spfile

sql statement: alter system set fal_server = ''MICKPRIM'' comment= '''' scope=spfile

sql statement: alter system set fal_client = ''MICKSTBY'' comment= '''' scope=spfile

sql statement: alter system set standby_file_management = ''AUTO'' comment= '''' scope=spfile

sql statement: alter system set db_file_name_convert = ''/oradata/MICKPRIM'', ''/oradata/MICKSTBY'' comment= '''' scope=spfile

sql statement: alter system set log_file_name_convert = ''/oradata/MICKPRIM'', ''/oradata/MICKSTBY'' comment= '''' scope=spfile

sql statement: alter system set log_archive_dest_1 = ''location=/oradata/MICKSTBY/arch valid_for=(all_logfiles,all_roles) db_unique_name=MICKSTBY'' comment= '''' scope=spfile

sql statement: alter system set log_archive_dest_2 = ''service=MICKPRIM valid_for=(online_logfiles,primary_role) db_unique_name=MICKPRIM'' comment= '''' scope=spfile

sql statement: alter system set log_archive_dest_state_1 = ''enable'' comment= '''' scope=spfile

sql statement: alter system set log_archive_dest_state_2 = ''defer'' comment= '''' scope=spfile

sql statement: alter system set db_unique_name = ''MICKSTBY'' comment= '''' scope=spfile

Oracle instance shut down

connected to auxiliary database (not started)
Oracle instance started

Total System Global Area 1068937216 bytes

Fixed Size 2260088 bytes
Variable Size 671089544 bytes
Database Buffers 390070272 bytes
Redo Buffers 5517312 bytes
allocated channel: c2
channel c2: SID=133 device type=DISK

contents of Memory Script:
{
 backup as copy current controlfile for standby auxiliary format '/oradata/MICKSTBY/control01.ctl';
}
executing Memory Script

Starting backup at 08-NOV-16
channel c1: starting datafile copy
copying standby control file
output file name=/oracle/product/11.2.0.4/dbs/snapcf_MICKPRIM.f tag=TAG20161108T172056 RECID=3 STAMP=927393657
channel c1: datafile copy complete, elapsed time: 00:00:03
Finished backup at 08-NOV-16

contents of Memory Script:
{
 sql clone 'alter database mount standby database';
}
executing Memory Script

sql statement: alter database mount standby database

contents of Memory Script:
{
 set newname for tempfile 1 to
 "/oradata/MICKSTBY/temp01.dbf";
 switch clone tempfile all;
 set newname for datafile 1 to
 "/oradata/MICKSTBY/system01.dbf";
 set newname for datafile 2 to
 "/oradata/MICKSTBY/sysaux01.dbf";
 set newname for datafile 3 to
 "/oradata/MICKSTBY/undotbs01.dbf";
 set newname for datafile 4 to
 "/oradata/MICKSTBY/users01.dbf";
 backup as copy reuse
 datafile 1 auxiliary format
 "/oradata/MICKSTBY/system01.dbf" datafile
 2 auxiliary format
 "/oradata/MICKSTBY/sysaux01.dbf" datafile
 3 auxiliary format
 "/oradata/MICKSTBY/undotbs01.dbf" datafile
 4 auxiliary format
 "/oradata/MICKSTBY/users01.dbf" ;
 sql 'alter system archive log current';
}
executing Memory Script

executing command: SET NEWNAME

renamed tempfile 1 to /oradata/MICKSTBY/temp01.dbf in control file

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

Starting backup at 08-NOV-16
channel c1: starting datafile copy
input datafile file number=00001 name=/oradata/MICKPRIM/system01.dbf
output file name=/oradata/MICKSTBY/system01.dbf tag=TAG20161108T172106
channel c1: datafile copy complete, elapsed time: 00:00:55
channel c1: starting datafile copy
input datafile file number=00002 name=/oradata/MICKPRIM/sysaux01.dbf
output file name=/oradata/MICKSTBY/sysaux01.dbf tag=TAG20161108T172106
channel c1: datafile copy complete, elapsed time: 00:00:35
channel c1: starting datafile copy
input datafile file number=00003 name=/oradata/MICKPRIM/undotbs01.dbf
output file name=/oradata/MICKSTBY/undotbs01.dbf tag=TAG20161108T172106
channel c1: datafile copy complete, elapsed time: 00:00:15
channel c1: starting datafile copy
input datafile file number=00004 name=/oradata/MICKPRIM/users01.dbf
output file name=/oradata/MICKSTBY/users01.dbf tag=TAG20161108T172106
channel c1: datafile copy complete, elapsed time: 00:00:01
Finished backup at 08-NOV-16

sql statement: alter system archive log current

contents of Memory Script:
{
 switch clone datafile all;
}
executing Memory Script

datafile 1 switched to datafile copy
input datafile copy RECID=3 STAMP=927393773 file name=/oradata/MICKSTBY/system01.dbf
datafile 2 switched to datafile copy
input datafile copy RECID=4 STAMP=927393773 file name=/oradata/MICKSTBY/sysaux01.dbf
datafile 3 switched to datafile copy
input datafile copy RECID=5 STAMP=927393773 file name=/oradata/MICKSTBY/undotbs01.dbf
datafile 4 switched to datafile copy
input datafile copy RECID=6 STAMP=927393773 file name=/oradata/MICKSTBY/users01.dbf
Finished Duplicate Db at 08-NOV-16
released channel: c1
released channel: c2

Et voila, nous avons notre base de secours en mode STANDBY sur notre serveur. Vérifions donc la configuration de la base pour activer le mode DATAGUARD et de facto la synchronisation automatique via l’application des archivelogs.

Sur le serveur et base PRIMAIRE, on vérifie la base et on récupère le dernier numéro de séquence d’archivelog généré :

SQL> select status,instance_name,database_role from v$database,v$instance;

STATUS INSTANCE_NAME DATABASE_ROLE
------------ ---------------- ----------------
OPEN MICKPRIM PRIMARY

SQL> select max(sequence#) from v$archived_log;

MAX(SEQUENCE#)
--------------
 28

On fait la même vérification sur la standby :

SQL> select status,instance_name,database_role from v$database,v$instance;

STATUS INSTANCE_NAME DATABASE_ROLE
------------ ---------------- ----------------
MOUNTED MICKSTBY PHYSICAL STANDBY

SQL> select max(sequence#) from v$archived_log where applied='YES';

MAX(SEQUENCE#)
--------------
 28

Nous avons donc les 2 bases au même niveau de séquence. Essayons voir si des archivelogs de la base primaire seraient automatiquement appliquées sur la base Standby :

Sur la base primary :

SQL> select status,instance_name,database_role from v$database,v$instance;

STATUS INSTANCE_NAME DATABASE_ROLE
------------ ---------------- ----------------
OPEN MICKPRIM PRIMARY

SQL> alter system switch logfile ;

System altered.

SQL> /

System altered.
SQL> /

System altered.
...
...
...
SQL> /

System altered.

SQL> select max(sequence#) from v$archived_log;

MAX(SEQUENCE#)
--------------
 36

On vérifie directement sur la base Standby, sans aucune autre action, en vérifiant tout d’abord si le transfert des archivelogs c’est bien fait entre les 2 machines :

[oracle@srvorastby arch]$ ls -ltr /oradata/MICKSTBY/arch
total 112708

-rw-r-----. 1 oracle dba 169984 Nov 28 09:44 1_34_928484905.arc
-rw-r-----. 1 oracle dba 22016 Nov 28 09:44 1_35_928484905.arc
-rw-r-----. 1 oracle dba 28672 Nov 28 09:44 1_33_928484905.arc
-rw-r-----. 1 oracle dba 6958592 Nov 28 09:44 1_29_928484905.arc
-rw-r-----. 1 oracle dba 6540800 Nov 28 09:44 1_30_928484905.arc
-rw-r-----. 1 oracle dba 19219968 Nov 28 09:44 1_32_928484905.arc
-rw-r-----. 1 oracle dba 41263616 Nov 28 09:44 1_31_928484905.arc
-rw-r-----. 1 oracle dba 19968 Nov 28 09:44 1_36_928484905.arc
-rw-r-----. 1 oracle dba 52429312 Nov 28 09:48 1_37_928484905.arc

Nous avons bien nos archives, de la séquence 29 à 37, qui ont été transférées automatiquement. Vérifions maintenant l’application coté base :

[oracle@srvorastby arch]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.4.0 Production on Tue Nov 8 17:45:14 2016

Copyright (c) 1982, 2013, Oracle. All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> select max(sequence#) from v$archived_log where applied='YES';

MAX(SEQUENCE#)
--------------
 28

=> Les archivelogs n’ont pas été appliquées à la base standby, ce qui est normal puisque nous n’avons pas activé l’application automatique des archivelogs. Qu’à cela ne tienne, j’active la synchronisation automatique :

SQL> alter database recover managed standby database disconnect from session;

Database altered.

SQL> select process,status,sequence# from v$managed_standby;

PROCESS STATUS SEQUENCE#
--------- ------------ ----------
RFS IDLE 0
RFS IDLE 0
RFS IDLE 39

PROCESS STATUS SEQUENCE#
--------- ------------ ----------
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
MRP0 APPLYING_LOG 30

Dans le contrôle ci dessus, que j’ai lancé directement après la commande de synchronisation, nous identifions deux processus importants pour le fonctionnement de Dataguard :
-> Le process RFS (remote file server) qui est en attente de la séquence 39 (Last séquence de la base primaire),

Dans sa définition la plus globale, le processus RFS récupère les informations des modifications qui ont eu lieu sur la base primaire (en interrogeant le processus LGWR), et les appliquent automatiquement en déclenchant le processus MRP dans les Standby redologs files.

-> Le process MRP (Managed Recovery Process) qui, quand à lui, est en charge de l’application des archivelogs reçues dans les STANDBY REDOLOGS FILES.

Qu’est ce dont ces standby redologs files ? Simple, ce sont des redologs similaires à des redologs normaux (Online Redo Log), sauf qu’ils sont utilisés uniquement pour enregistrer des données depuis une base distante.

Vérifions après quelques instant la base stanbdby,  qui a du appliquer toutes les archivelogs reçues de la base PRIMARY :

SQL> select max(sequence#) from v$archived_log where applied='YES';

MAX(SEQUENCE#)
--------------
 38

SQL> select process,status,sequence# from v$managed_standby;

PROCESS STATUS SEQUENCE#
--------- ------------ ----------
ARCH CONNECTED 0
ARCH CONNECTED 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 39
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
MRP0 WAIT_FOR_LOG 39

SQL> select DEST_NAME,RECOVERY_MODE,DATABASE_MODE,TYPE,STATUS,DESTINATION from v$archive_dest_status ;

DEST_NAME RECOVERY_MODE DATABASE_MODE STATUS DESTINATION
------------------------- ----------------------------------- --------------- --------- ------------------------------
LOG_ARCHIVE_DEST_1 MANAGED MOUNTED-STANDBY VALID /oradata/MICKSTBY/arch
LOG_ARCHIVE_DEST_2 IDLE UNKNOWN DEFERRED WITTPRDH

-> Les archivelogs ont bien été appliquées automatiquement et continueront à l’être, nous voyons bien que la base Standby est en « MANAGED » (ie : application des archives automatiquement gérée) !

Bon, nous avons bien toutes les archivelogs appliquées, et notre process MRP en waiting, preuve que la base STANDBY est en mode de d’application automatique des archivelogs dans les standby redologs files.

Et voilà, nous avons monté un mécanisme de Dataguard Physical, mis en place la synchronisation automatique, et vérifié que tout ce petit monde s’accorde correctement.

Mais qu’en est il si nous modifions le mode de protection de Dataguard ? Si nous passions en Maximum PROTECTION ou AVAILABILITY ?

Cela tombe bien, nous allons voir cela très prochainement dans le second article « Oracle Dataguard 11G Part #2 : Comment changer le mode de protection de Dataguard  »

Enjoy !

Micka