Skip to main content

HA niveau 2 - Standby database logical from physical with RMAN from active database

Basé principalement sur http://www.oracledistilled.com/oracle-database/high-availability/data-guard/creating-a-physical-standby-using-rman-duplicate-from-active-database/
Physical standby : https://oracle-base.com/articles/11g/data-guard-setup-11gr2

On ne peut pas créer directement une LOGICAL STANDBY avec RMAN. Il faut d’abord créer une PHYSICAL STANDBY, puis la convertir en LOGICAL.

PHYSICAL STANDBY

Primary database informations :
Host: ocm1.odlabs.net
DB_NAME = pritst
DB_UNIQUE_NAME=pritst

Standby database information :
Host: ocm2.odlabs.net
DB_NAME = pritst
DB_UNIQUE_NAME = stbytst

LE DB_UNIQUE_NAME DE LA STANDBY EST DONC DIFFERENT. Ce paramètre n’est pas modifié sur tous les tutos relatif aux standby databases. Cependant Oracle précise :

"A database in an Oracle Data Guard environment is uniquely identified by means of the DB_UNIQUE_NAME parameter in the initialization parameter file. The DB_UNIQUE_NAME must be unique across all the databases with the same DBID for RMAN to work correctly in an Oracle Data Guard environment."

NOTE : la Standard Edition dispose bien de Dataguard mais pas du Managed Standby (envoi et application automatique des archives par Oracle). Ce n'est disponible que dans l'Enterprise (avec option payante !). La procédure ci-dessous s'applique donc à une version Enterprise.

Pour une Standard Edition, il faudra copier manuellement les archives vers la Standby, puis les appliquer également manuellement (par un script à intervalles réguliers, par exemple).

SUR LA PRIMARY

1. La base doit être en ARCHIVELOG FORCE_LOGGING

SQL> select log_mode,force_logging from v$database;
SQL> alter database force logging;

2. Doubler les REDO LOGS par des STANDBY REDO LOGS de taille identiques, mais créer un groupe de plus que les REDO standards

SQL> select group#, thread#, bytes/1024/1024 from v$log;
SQL> alter database add standby logfile '/u01/app/oracle/oradata/pritst/stby_redo01.log' size 50M;
SQL> alter database add standby logfile '/u01/app/oracle/oradata/pritst/stby_redo02.log' size 50M;
SQL> alter database add standby logfile '/u01/app/oracle/oradata/pritst/stby_redo03.log' size 50M;
SQL> alter database add standby logfile '/u01/app/oracle/oradata/pritst/stby_redo04.log' size 50M;

3. Vérifier les DB_*_NAME...

SQL> show parameter db_name
db_name string pritst

SQL> show parameter db_unique_name
db_unique_name string pritst

...Et indiquer le DB_UNIQUE_NAME dans LOG_ARCHIVE_CONFIG

SQL> show parameter LOG_ARCHIVE_CONFIG
log_archive_config string

SQL> alter system set log_archive_config='DG_CONFIG=(pritst,stbytst)';

4. Modifier LOG_ARCHIVE_DEST_1 et LOG_ARCHIVE_DEST_2

SQL> show parameter log_archive_dest_1
log_archive_dest_1 string LOCATION=/u01/app/oracle/oradata/pritst/arch

SQL> alter system set LOG_ARCHIVE_DEST_1='LOCATION=/u01/app/oracle/oradata/pritst/arch/ VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=pritst';
SQL> alter system set LOG_ARCHIVE_DEST_STATE_1=ENABLE;

SQL> alter system set LOG_ARCHIVE_DEST_STATE_2=DEFER; # enable it ONLY after creating logical standby
SQL> show parameter LOG_ARCHIVE_DEST_2
log_archive_dest_2 string
SQL> alter system LOG_ARCHIVE_DEST_2='SERVICE=DESTTST LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=stbytst';

-- Attention : nom TNS de la base standby dans "SERVICE"

SQL> alter system set LOG_ARCHIVE_MAX_PROCESSES=16; # it should be between 4 and 30

Rappel :

Sur Standard Edition, l'archive_dest_2 ne fonctionne pas sur la primary, mais en copiant les archives à la main et en appliquant :

SQL> recover standby database;

il rejoue alors les archives présentes. Cette procédure manuelle fonctionne donc pour la standby, même si c'est pour une Enterprise.

Par contre attention sur une Standard si LOG_ARCHIVE_DEST_2 a été paramétré, la primary remplit ses traces car elle ne sait pas envoyer les archives automatiquement ! On peut paramétrer LOG_ARCHIVE_DEST_STATE_2=DEFER (comme indiqué ci-dessus) en attendant.

5. FAL_SERVER est la base primary et FAL_CLIENT est la standby.

SQL> alter system set fal_server=pritst;
SQL> alter system set fal_client=stbytst;

6. Il faut logguer les ajouts/suppression de fichiers aussi

SQL> alter system set standby_file_management=auto;

* NOTE : tout ça (et même plus) peut éventuellement être ajouté dans un bloc RUN de RMAN :

run {
	sql channel prmy1 "alter system set log_archive_config=''DG_CONFIG=(pritst,stbytst)''";
    sql channel prmy1 "alter system set log_archive_dest_2=''SERVICE=stbytst LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=stbytst''";
    sql channel prmy1 "alter system set log_archive_max_processes=5";
    sql channel prmy1 "alter system set fal_client=stbytst";
    sql channel prmy1 "alter system set fal_server=pritst";
    sql channel prmy1 "alter system set standby_file_management=AUTO";
    sql channel prmy1 "alter system set log_archive_dest_state_1=enable";
    sql channel prmy1 "alter system archive log current";
    sql channel stby "alter database recover managed standby database using current logfile disconnect from session";
    }

7. Et s'assurer que le REMOTE LOGING est activé
(rappel : password file créé par : orapwd file=orapwtestgg1 password=test entries=5)

SQL > show parameter password
SQL > alter system set remote_login_passwordfile=exclusive;

8. LISTENER : les bases doivent être gérée STATIQUEMENT. Ajouter aux 2 listerner.ora :

SID_LIST_LISTENER =
	(SID_LIST =
    	(SID_DESC =
        	(SID_NAME = pritst)
            (ORACLE_HOME = /u01/app/oracle/product/11.2.0/dbhome_1)
        )
    )

9. Ajouter les 2 bases aux tnsnames des 2 serveurs

SOURCETST =
	(DESCRIPTION =
    	(ADDRESS = (PROTOCOL = TCP)(HOST = ocm1.odlabs.net)(PORT = 1521))
        (CONNECT_DATA =
        	(SERVER = DEDICATED)
        	(SERVICE_NAME = pritst)
    	)
    )

DESTTST =
	(DESCRIPTION =
    	(ADDRESS = (PROTOCOL = TCP)(HOST = ocm2.odlabs.net)(PORT = 1521))
        (CONNECT_DATA =
        	(SERVER = DEDICATED)
            (SERVICE_NAME = pritst)(UR=A)
# attention : le listener prend le DB_UNIQUE_NAME si la base n'est pas définie statiquement.
# « UR=A » nécessaire car la secondary démarrée en NOMOUNT n'acceptera pas les connexions ("BLOCKED" au lsnrctl status). Ce paramètre permet de passer outre.
		)
    )

SUR LA SECONDARY

1.préparer le terrain pour RMAN

* Note : penser au sysctl.conf si pas déjà fait par l’installation d’Oracle

- Soit manuellement :

Créer l'arborescence :

[oracle@ocm2 ~]$ mkdir oradata
[oracle@ocm2 ~]$ mkdir oradata/pritst
[oracle@ocm2 ~]$ mkdir oradata/pritst/arch
[oracle@ocm2 ~]$ mkdir /u01/app/oracle/admin
[oracle@ocm2 ~]$ mkdir /u01/app/oracle/admin/pritst
[oracle@ocm2 ~]$ mkdir /u01/app/oracle/admin/pritst/adump
[oracle@ocm2 ~]$ mkdir /u01/app/oracle/admin/pritst/bdump
[oracle@ocm2 ~]$ mkdir /u01/app/oracle/admin/pritst/dpdump
[oracle@ocm2 ~]$ mkdir /u01/app/oracle/admin/pritst/pfile

et ajouter dans /etc/oratab :

pritst:/u01/app/oracle/product/11.2.0/dbhome_1:N

- OU simplement en créant une base identique à la primary, vide.

2. Créer un LISTENER (si base créée manuellement), et enregistrer statiquement la standby

SID_LIST_LISTENER =
	(SID_LIST =
		(SID_DESC =
			(SID_NAME = pritst)
			(ORACLE_HOME = /u01/app/oracle/product/11.2.0/dbhome_1)
		)
	)

$ lsnrctl start

3. S'assurer que TNS connaît bien les 2 bases par tnsping

4. Créer un init.ora basique

$ cat initpritst.ora
DB_NAME=pritst
DB_UNIQUE_NAME=stbytst

si base a été créée par dbca, crée le pfile à partir du spfile :

SQL> create pfile from spfile ;

et y modifier DB_UNIQUE_NAME, supprimer le spfile et redémarrer la base en NOMOUNT.

5. recopier le password file du primary (important : il ne faut pas le recréer mais reprendre celui du primary)

$ scp oracle@ocm1:$ORACLE_HOME/dbs/orapwpritst $ORACLE_HOME/dbs

6. Lancer la base en NOMOUNT
La base démarre avec le PFILE si on s’est assuré que le spfile a bien été supprimé.
Sortir de la session sqlplus ensuite pour ne pas bloquer RMAN

$ sqlplus / as sysdba
Connected to an idle instance.
SQL> startup nomount
SQL> exit

7. fichier de commande de réplication RMAN (toujours sur la standby) dupstby.cmd

run {
 allocate channel pri1 type disk;
 allocate channel pri2 type disk;
 allocate channel prmy4 type disk;
 allocate auxiliary channel stby type disk;
  
 duplicate target database 
  for standby 
  from active database
  dorecover
  spfile
    set db_unique_name='stbytst'
    set control_files='/u01/app/oracle/oradata/pritst/control01.ctl','/u01/app/oracle/oradata/pritst/control02.ct'
    set fal_client='pritst'
    set fal_server='stbytst'
    set standby_file_management='AUTO'
    set log_archive_config='dg_config=(pritst,stbytst)'
    set log_archive_dest_1='LOCATION=/u01/app/oracle/oradata/pritst/arch/ VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=stbytst'
    set log_archive_dest_2='service=sourcetst ASYNC valid_for=(ONLINE_LOGFILE,PRIMARY_ROLE) db_unique_name=pritst'
  nofilenamecheck;
  }

* Noter l'inversion de pritst et stbytst dans log_archive_dest_1 et log_archive_dest_2

* Si l'arborescence n'est pas la même que sur le primary, ajouter :

set db_file_name_convert='<chemin des fichiers PRYMARY>','<chemin des fichiers SECONDARY>'
set log_file_name_convert='<chemin des fichiers PRYMARY>','<chemin des fichiers SECONDARY>'

8. se connecter aux 2 bases pour lancer le script

* S'assurer que chacun des serveurs se connecte à la base de l'autre via TNS avec SYS

* Si la secondary n'a pas été mise en archivelog par dbca, le répertoire archive n'existe peut-être pas ! Créer le même que dans le paramètre LOG_ARCHIVE_DEST_1 qui arrivera de la primary, et vérifier les droits !

* LA BASE PRIMAIRE DOIT AVOIR ETE DEMARREE AVEC UN SPFILE, sinon RMAN refuse de lancer la duplication !

$ rman
Recovery Manager: Release 11.2.0.1.0 - Production on Fri Jul 13 16:47:46 2012
Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.

RMAN> connect target sys/password@SOURCETST
connected to target database: PRITST (DBID=3720300117)

RMAN> connect auxiliary sys/password@DESTTST
connected to auxiliary database: PRITST (not mounted)

OU :

$ rman target sys/password@SOURCETST auxiliary sys/password@DESTTST

* NOTE : en cas de plantage de RMAN, après correction de l’erreur, penser à supprimer le spfile qui a pu être créé juste avant le plantage

RMAN> @dupstby.cmd

9. A la fin de la duplication, lancer le processus de recovery

$ sqlplus / as sysdba

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

en cas d'erreur ORA-01153 :

SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT FROM SESSION;
SQL> exit

10. Vérifier l’application des REDO LOGS (via les ARCHIVE LOGS)

SQL> select sequence#, first_time, next_time, applied from v$archived_log order by sequence#;

en forçant sur la PRIMARY un switch :

SQL> alter system switch logfile;


Optionnel

Choisir le niveau de sécurité sur la PRIMARY (MAXIMUM PERFORMANCE par défaut)

SQL> SELECT protection_mode FROM v$database;
MAXIMUM PERFORMANCE

Choisir un des modes :

Maximum Performance // Default
Transactions on the primary commit as soon as redo information has been written to the online redo log. Transfer of redo information to the standby server is asynchronous.

SQL> ALTER SYSTEM SET LOG_ARCHIVE_DEST_2='SERVICE=stbytst NOAFFIRM ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=stbytst';
SQL> ALTER DATABASE SET STANDBY DATABASE TO MAXIMIZE PERFORMANCE;

Maximum Availability
Transactions on the primary do not commit until redo information has been written to the online redo log and the standby redo logs of at least one standby location. If no standby location is available, it acts in the same manner as maximum performance mode until a standby becomes available again.

SQL> ALTER SYSTEM SET LOG_ARCHIVE_DEST_2='SERVICE=stbytst AFFIRM SYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=stbytst';
SQL> ALTER DATABASE SET STANDBY DATABASE TO MAXIMIZE AVAILABILITY;

Maximum Protection
Transactions on the primary do not commit until redo information has been written to the online redo log and the standby redo logs of at least one standby location.If not suitable standby location is available, the primary database shuts down.

SQL> ALTER SYSTEM SET LOG_ARCHIVE_DEST_2='SERVICE=DESTTST AFFIRM SYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=stbytst';
SQL> SHUTDOWN IMMEDIATE;
SQL> STARTUP MOUNT;
SQL> ALTER DATABASE SET STANDBY DATABASE TO MAXIMIZE PROTECTION;
SQL> ALTER DATABASE OPEN;

READ-ONLY STANDBY

On peut passer une base PHYSICAL STANDBY momentanément en READ ONLY afin de l’interroger.

SQL>alter database recover managed standby database cancel;
SQL>alter database open read only;
SQL>select open_mode from v$database;
SQL>alter database recover managed standby database using current logfile disconnect;
SQL>select open_mode from v$database;
	-- doit indiquer "READ ONLY WITH APPLY"

REDEMARRAGE DE LA STANDBY :

-- Start the database:
SQL> STARTUP NOMOUNT;

-- Mount the standby database:
SQL> ALTER DATABASE MOUNT STANDBY DATABASE;

-- Start the managed recovery operation:
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;

CONVERSION PHYSICAL EN LOGICAL STANDBY

Basé sur :

https://chenguangblog.wordpress.com/2011/02/09/creating-logical-standby-database/
https://docs.oracle.com/cd/E11882_01/server.112/e41134/create_ls.htm#SBYDB4737
http://rajiboracle.blogspot.fr/2017/01/how-to-convert-physical-standby-to.html

Après création d’une physical standby avec RMAN, vérifier si des types sont incompatibles avec standby dans la base source :

SQL> select OWNER, TABLE_NAME, COLUMN_NAME, ATTRIBUTES, DATA_TYPE from dba_logstdby_unsupported;

Eventuellement, convertir ou modifier les types incompatibles.

1. Sur la PRIMARY, créer un répertoire archive supplémentaire (utilisé si la primary est switchée en standby)

mkdir /u01/oradata/orcl/stbyarchives

2. Modifier LOG_ARCHIVE_DEST_1 uniquement pour les REDO primary (ONLINE_LOGFILES), et créer un LOG_ARCHIVE_DEST_3 utilisé si la base switche en standby

SQL> alter system set log_archive_dest_1='LOCATION=/u01/app/oracle/oradata/pritst/arch/ VALID_FOR=(ONLINE_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=pritst';
SQL> alter system set LOG_ARCHIVE_DEST_3='LOCATION=/u01/app/oracle/oradata/orcl/stbyarchives VALID_FOR=(STANDBY_LOGFILES,STANDBY_ROLE)';

3. Stopper et redémarrer au moins une fois la standby après création

SQL> shutdown immediate;
SQL> startup nomount;
SQL> alter database mount standby database;
SQL> alter database recover managed standby database disconnect from session;

4. S'assurer que les logs sont au même niveau sur les 2 bases

SQL> select sequence#, first_time, next_time, applied from v$archived_log order by sequence#;

5. Sur la standby, stopper le processus managed recovery

SQL> alter database recover managed standby database cancel;

6. Sur la primary, lancer la construction des tables LogMiner pour le dictionnaire

SQL> begin
dbms_logstdby.build;
end;
/

7. Sur la standby, lancer la conversion en LOGICAL

SQL> alter database recover to logical standby STBYORCL; # DB_UNIQUE_NAME de la standby

* Si problème, stopper le processus dans une autre session par :

SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;

8. Générer quelques log switchs sur la primary pour s’assurer que les archives sont créées et envoyées vers la standby

SQL> alter system switch logfile;

9. Sur la standby, la commande « alter database... » se termine après un certain temps.

En cas d’erreur :

ERROR at line 1:
ORA-20000: File /u01/app/oracle/oradata/pritst/temp01.dbf has wrong dbid or
dbname, remove or restore the offending file.

(qui n’est pas bloquante), recréer tout de suite le tablespace TEMP.

La base est désormais une LOGICAL STANDBY, on peut le voir dans l’alert.log :

RFS[12]: Identified database type as 'logical standby'

10. Relancer la standby

SQL> shutdown immediate
SQL> startup mount
SQL> alter database open resetlogs;

11. Sur la standby, paramétrer un LOG_ARCHIVE_DEST_3 utilisé si la base switche en primary

SQL> alter system set LOG_ARCHIVE_DEST_3='LOCATION=/u01/app/oracle/oradata/orcl/stbyarchives VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE)';

12. Il reste à lancer le processus SQL Apply

SQL> alter database start logical standby apply immediate;

Désormais les changements détectés dans les ARCHIVE sont rejoués en SQL, la base est par ailleurs ouverte pour d’autres requêtes, même de modifications.