Cloner une base de données sans sauvegarde en 11g

Remarque préliminaire :
Ce post suppose que vous utilisiez Oracle Database 11.1 ou supérieure. Les tests ont été réalisés avec une version 11.1.0.6 sur Linux Ubuntu et nécessiteront sans doute quelques ajustements pour une autre version ou un autre environnement. Quoiqu’il en soit, testez toujours une methode avant de l’appliquer à un de vos environnements.

Comme dans mon précédent post, j’ai cette chanson dans ma tête : « Comment cloner une base de données dans ASM ? ». Voici une nouvelle tentative de réponse, cette fois avec la commande DUPLICATE de RMAN et sans passez par les étapes de sauvegarde ni de transport de la sauvegarde entre plusieurs serveurs… Nous nous appuyerons sur la clause FROM ACTIVE DATABASE de la commande RMAN DUPLICATE ; il s’agit d’une de ces nouveautés 11g.

Supposons pour faire simple que vous avez une base de données avec son instance BLUJ sur une machine blue et que vous vouliez créer une base de données REDX sur une machine red. Pour corser un peu l’affaire, et rendre possible la manipulation sur un seul serveur, disons que la base de données est dans le Disk Group DGBLUJ sur blue et que vous voulez la copier dans le Disk Group DGREDX sur red. Voilà pour les hypothèses ; maintenant, comment faire ?

Etape 1 : Créer l’environnement sur le serveur cible

Dans cette première étape, vous allez mettre en place quelques fichiers indispensables pour démarrer. Un des pré-requis pour utiliser la commande DUPLICATE FROM ACTIVE DATABASE est d’avoir une instance cible accessible (i.e démarrée en mode NOMOUNT) via un alias Oracle*Net, il faut donc évidemment :

  • Avoir le logiciel installé Oracle Database 11g ou supérieur sur votre serveur cible ; la même version que sur votre machine source
  • Avoir ASM démarré et le(s) Disk Group(s) cible(s) monté(s)

Une fois ces étapes de préparations effectuées, vous allez démarrer l’instance cible. Pour cela, il est d’abord conseillé d’ajouter une ligne pour votre instance dans /etc/oratab comme ci-dessous (Sous Windows, utilisez oradim) :

$ grep REDX /etc/oratab
REDX:/u01/app/oracle/product/11.1.0/db_1:N

Ensuite créez un fichier de mots de passe puisqu’il faudra vous connecter depuis la machine source alors que la base de données n’est pas ouverte. Utilisez la commande orapwd comme ci-dessous :

$ cd $ORACLE_HOME/dbs
$ orapwd file=orapwREDX password=change_on_install entries=5
$ history -c

Soyez attentif que le nom et l’emplacement du fichier de mot de passe depend du système d’exploitation. Enfin pour terminer, créez un fichier init.ora (le SPFILE sera créé par le DUPLICATE). Voici un exemple typique d’un tel fichier sous Linux (Si vous n’utilisez pas les huge pages, ce que je ne recommande pas)

$ cat initREDX.ora
memory_target=300M
processes=80
db_name='REDX'
remote_login_passwordfile='exclusive'

Remarquez bien que le positionnement de la variable ORACLE_BASE est désormais obligatoire avec 11g et que, du coup, vous n’avez besoin que de ces 4 paramètres pour démarrer votre instance. Etape que vous pouvez compléter comme ci-dessous :

$ . oraenv
ORACLE_SID = [+ASM] ? REDX
The Oracle base for ORACLE_HOME=/u01/app/oracle/product/11.1.0/db_1 is /u01/app/oracle

$ sqlplus / as sysdba

SQL> startup nomount

Etape 2: Configurer les accès réseaux

La commande DUPLICATE FROM ACTIVE DATABASE nécessite que la base de données source se connecte à la base de données cible et que des opérations telles que le démarrage et l’arrêt de l’instance soient effectuées à distance. Il est donc indispensable qu’il y ait un fichier de mots de passe sur les 2 environnements et que l’on puisse se connecter SYSDBA via le réseau. Il faut, en outre, que l’instance cible soit enregistrée de manière statique dans son listener et que le descripteur de connexion vers la cible utilise SID pour se connecter et non pas SERVICE_NAME.

Commençons par le listener sur la machine cible. Son fichier de configuration listener.ora doit ressembler à celui ci-dessous et comporter en particulier la clause SID_LIST_{LISTENER_NAME} qui permet d’enregistrer l’instance et son ORACLE_HOME de manière statique dans le listener.

$ cat listener.ora

LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = red)(PORT = 1521))
)
)

SID_LIST_LISTENER=
(SID_LIST=
(SID_DESC=
(ORACLE_HOME=/u01/app/oracle/product/11.1.0/db_1)
(SID_NAME=REDX)
)
)

Si vous utiliser des alias TNS stockés dans des fichiers tnsnames.ora, ce qui reste la méthode la plus courante malgré EZCONNECT, vos fichiers doivent contenir les alias pour la source et pour la cible ; le descripteur de votre cible doit contenir le mot clé SID comme ci-dessous :

$ cat tnsnames.ora
REDX=(DESCRIPTION=
(ADDRESS=(HOST=red)(PORT=1521)(PROTOCOL=TCP))
(CONNECT_DATA=(SID=REDX))
)

De cette manière, vous pouvez vous connecter à votre base cible par le réseau, même après l’avoir arrêtée :

$ . oraenv
ORACLE_SID = [+ASM] ? REDX
The Oracle base for ORACLE_HOME=/u01/app/oracle/product/11.1.0/db_1 is /u01/app/oracle

$ sqlplus / as sysdba

SQL> shutdown abort

SQL> connect sys@redx as sysdba

Connected to an idle instance.

Etape 3 : Derniers préparatifs sur l’environnement cible avant de démarrer l’opération.

Vérifiez les paramètres de votre environnement source et adaptez votre environnement cible en conséquence. Par exemple, dans mon cas, audit_dump_dest utilise $ORACLE_BASE/admin/BLUJ/adump. Je crée donc le répertoire correspondant (Ce n’est pas la peine de créer les répertoires de admin_dest, le système le fera seul) :

$ mkdir -p $ORACLE_BASE/admin/REDX/adump

Etape 4 : Cloner la base de données :

Et oui, ça ne fait que quelques minutes que vous avez démarrés et vous en êtes dejà à la conclusion. Connectez-vous à la base source (mot clé target) et la base cible (mot clé auxiliary) avec RMAN et démarrez la cible en mode nomount si ce n’est pas déjà le cas :

$ rman target=sys@bluj auxiliary=sys@redx

Recovery Manager: Release 11.1.0.6.0 - Production on Sun Feb 10 16:29:20 2008

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

connected to target database: BLUJ (DBID=1974909803)
connected to auxiliary database (not started)

RMAN> startup clone nomount;

Oracle instance started

Total System Global Area 209235968 bytes
Fixed Size 1298920 bytes
Variable Size 71306776 bytes
Database Buffers 134217728 bytes
Redo Buffers 2412544 bytes

Une fois l’opération effectuée, lancer la commande duplicate comme ci-dessous :

RMAN> DUPLICATE TARGET DATABASE
TO REDX
FROM ACTIVE DATABASE
DB_FILE_NAME_CONVERT '+DGBLUJ','+DGREDX'
NOFILENAMECHECK
SPFILE
PARAMETER_VALUE_CONVERT '+DGBLUJ','+DGREDX','BLUJ','REDX'
SET LOG_FILE_NAME_CONVERT '+DGBLUJ','+DGREDX'
SET PGA_AGGREGATE_TARGET '80M'
SET SGA_TARGET '200M';

Quelques explications :

  • TO indique le nom de la base de données qui peut être différent de l’instance. A la fin de l’opération de restore/recover le duplicate renomme en effet la base de données.
  • FROM ACTIVE DATABASE indique que le
    duplicate n’utilise pas de backup mais envoie les fichiers de base de données par Oracle*Net à l’autre instance
  • DB_FILE_NAME_CONVERT permet de renommer les Disk Group lors de l’opération. Dans l’exemple, il n’y a qu’un mapping ( DGBLUJ devient DGREDX) mais vous pouvez en avoir plusieurs
  • NOFILENAMECHECK indique que les noms des fichiers seront différents entre la source et la cible. Nous sommes obligé d’utiliser cette clause avec DB_FILE_NAME_CONVERT
  • SPFILE indique que le SPFILE va être copie de l’environnement source et les mots clés suivants y sont attachés :
    • PARAMETER_VALUE_CONVERT permet de changer le contenu des paramètres du SPFILE en mettant en place des correspodances entre des chaînes de caractères (ici, DGBLUJ devient DGREDX et BLUJ devient REDX)
    • SET permet de positionner des paramètres en particulier pour ajouter des informations spécifiques à l’instance cible ou changer des valeurs existance sur l’instance source
    • LOG_FILE_NAME_CONVERT permet de modifier la destination des fichiers de Redo Log lorsque ceux-ci seront créés dans le fichier de contrôle.

Etape 5 : Visualiser le deroulement de l’opération.

Avec Linux ou Unix, utilisez VNC ou nohup ; l’exécution du DUPLICATE FROM ACTIVE DATABASE ressemble à ceci :

Starting Duplicate Db at 10-FEB-08
using target database control file instead of recovery catalog
allocated channel: ORA_AUX_DISK_1
channel ORA_AUX_DISK_1: SID=75 device type=DISK

contents of Memory Script:
{
backup as copy reuse
file '+DGBLUJ/bluj/spfilebluj.ora' auxiliary format
'/u01/app/oracle/product/11.1.0/db_1/dbs/spfileREDX.ora' ;
sql clone "alter system set spfile= ''/u01/app/oracle/product/11.1.0/db_1/dbs/spfileREDX.ora''";
}
executing Memory Script

Starting backup at 10-FEB-08
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=134 device type=DISK
Finished backup at 10-FEB-08

sql statement: alter system set spfile= ''/u01/app/oracle/product/11.1.0/db_1/dbs/spfileREDX.ora''

contents of Memory Script:
{
sql clone "alter system set db_name =
''REDX'' comment=
''duplicate'' scope=spfile";
sql clone "alter system set audit_file_dest =
''/u01/app/oracle/admin/REDX/adump'' comment=
'''' scope=spfile";
sql clone "alter system set control_files =
''+DGREDX/bluj/controlfile/current.267.646310763'', ''+DGREDX/bluj/controlfile/current.268.646310765'' comment=
'''' scope=spfile";
sql clone "alter system set db_create_file_dest =
''+DGREDX'' comment=
'''' scope=spfile";
sql clone "alter system set db_recovery_file_dest =
''+DGREDX'' comment=
'''' scope=spfile";
sql clone "alter system set dispatchers =
''(PROTOCOL=TCP) (SERVICE=REDXXDB)'' comment=
'''' scope=spfile";
sql clone "alter system set log_archive_dest_1 =
''location=+DGREDX'' comment=
'''' scope=spfile";
sql clone "alter system set LOG_FILE_NAME_CONVERT =
''+DGBLUJ'', ''+DGREDX'' comment=
'''' scope=spfile";
sql clone "alter system set PGA_AGGREGATE_TARGET =
80M comment=
'''' scope=spfile";
sql clone "alter system set SGA_TARGET =
200M comment=
'''' scope=spfile";
shutdown clone immediate;
startup clone nomount ;
}
executing Memory Script

sql statement: alter system set db_name = ''REDX'' comment= ''duplicate'' scope=spfile

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

sql statement: alter system set control_files = ''+DGREDX/bluj/controlfile/current.267.646310763'', ''+DGREDX/bluj/controlfile/current.268.646310765'' comment= '''' scope=spfile

sql statement: alter system set db_create_file_dest = ''+DGREDX'' comment= '''' scope=spfile

sql statement: alter system set db_recovery_file_dest = ''+DGREDX'' comment= '''' scope=spfile

sql statement: alter system set dispatchers = ''(PROTOCOL=TCP) (SERVICE=REDXXDB)'' comment= '''' scope=spfile

sql statement: alter system set log_archive_dest_1 = ''location=+DGREDX'' comment= '''' scope=spfile

sql statement: alter system set LOG_FILE_NAME_CONVERT = ''+DGBLUJ'', ''+DGREDX'' comment= '''' scope=spfile

sql statement: alter system set PGA_AGGREGATE_TARGET = 80M comment= '''' scope=spfile

sql statement: alter system set SGA_TARGET = 200M comment= '''' scope=spfile

Oracle instance shut down

connected to auxiliary database (not started)
Oracle instance started

Total System Global Area 209235968 bytes

Fixed Size 1298920 bytes
Variable Size 71306776 bytes
Database Buffers 134217728 bytes
Redo Buffers 2412544 bytes
RMAN-05529: WARNING: DB_FILE_NAME_CONVERT resulted in invalid ASM names; names changed to disk group only.

contents of Memory Script:
{
set newname for datafile 1 to
"+dgredx";
set newname for datafile 2 to
"+dgredx";
set newname for datafile 3 to
"+dgredx";
set newname for datafile 4 to
"+dgredx";
backup as copy reuse
datafile 1 auxiliary format
"+dgredx" datafile
2 auxiliary format
"+dgredx" datafile
3 auxiliary format
"+dgredx" datafile
4 auxiliary format
"+dgredx" ;
sql 'alter system archive log current';
}
executing Memory Script

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

Starting backup at 10-FEB-08
using channel ORA_DISK_1
channel ORA_DISK_1: starting datafile copy
input datafile file number=00001 name=+DGBLUJ/bluj/datafile/system.277.646310619
output file name=+DGREDX/redx/datafile/system.269.646333827 tag=TAG20080210T171025 RECID=0 STAMP=0
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:01:36
channel ORA_DISK_1: starting datafile copy
input datafile file number=00002 name=+DGBLUJ/bluj/datafile/sysaux.276.646310623
output file name=+DGREDX/redx/datafile/sysaux.268.646333925 tag=TAG20080210T171025 RECID=0 STAMP=0
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:01:05
channel ORA_DISK_1: starting datafile copy
input datafile file number=00003 name=+DGBLUJ/bluj/datafile/undotbs1.275.646310625
output file name=+DGREDX/redx/datafile/undotbs1.267.646333989 tag=TAG20080210T171025 RECID=0 STAMP=0
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:03
channel ORA_DISK_1: starting datafile copy
input datafile file number=00004 name=+DGBLUJ/bluj/datafile/users.274.646310625
output file name=+DGREDX/redx/datafile/users.266.646333991 tag=TAG20080210T171025 RECID=0 STAMP=0
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:03
Finished backup at 10-FEB-08

sql statement: alter system archive log current
sql statement: CREATE CONTROLFILE REUSE SET DATABASE "REDX" RESETLOGS ARCHIVELOG
MAXLOGFILES 16
MAXLOGMEMBERS 3
MAXDATAFILES 100
MAXINSTANCES 8
MAXLOGHISTORY 292
LOGFILE
GROUP 1 ( '+dgredx', '+dgredx' ) SIZE 50 M REUSE,
GROUP 2 ( '+dgredx', '+dgredx' ) SIZE 50 M REUSE,
GROUP 3 ( '+dgredx', '+dgredx' ) SIZE 50 M REUSE
DATAFILE
'+DGREDX/redx/datafile/system.269.646333827'
CHARACTER SET WE8ISO8859P15


contents of Memory Script:
{
backup as copy reuse
archivelog like "+DGBLUJ/bluj/archivelog/2008_02_10/thread_1_seq_7.272.646333995" auxiliary format
"+DGREDX" ;
catalog clone recovery area;
switch clone datafile all;
}
executing Memory Script

Starting backup at 10-FEB-08
using channel ORA_DISK_1
channel ORA_DISK_1: starting archived log copy
input archived log thread=1 sequence=7 RECID=8 STAMP=646333995
output file name=+DGREDX/redx/archivelog/2008_02_10/thread_1_seq_7.262.646333999 RECID=0 STAMP=0
channel ORA_DISK_1: archived log copy complete, elapsed time: 00:00:01
Finished backup at 10-FEB-08

searching for all files in the recovery area

List of Files Unknown to the Database
=====================================
File Name: +dgredx/REDX/ARCHIVELOG/2008_02_10/thread_1_seq_7.262.646333999
File Name: +dgredx/REDX/DATAFILE/SYSAUX.268.646333925
File Name: +dgredx/REDX/DATAFILE/UNDOTBS1.267.646333989
File Name: +dgredx/REDX/DATAFILE/USERS.266.646333991
cataloging files...
cataloging done

List of Cataloged Files
=======================
File Name: +dgredx/REDX/ARCHIVELOG/2008_02_10/thread_1_seq_7.262.646333999
File Name: +dgredx/REDX/DATAFILE/SYSAUX.268.646333925
File Name: +dgredx/REDX/DATAFILE/UNDOTBS1.267.646333989
File Name: +dgredx/REDX/DATAFILE/USERS.266.646333991

List of files in Recovery Area not managed by the database
==========================================================
File Name: +DGREDX/redx/controlfile/current.256.646333997
RMAN-07527: Reason: File was not created using DB_RECOVERY_FILE_DEST initialization parameter
File Name: +DGREDX/redx/datafile/system.269.646333827
RMAN-07527: Reason: File was not created using DB_RECOVERY_FILE_DEST initialization parameter

number of files not managed by recovery area is 2, totaling 9.59MB

datafile 2 switched to datafile copy
input datafile copy RECID=4 STAMP=646334001 file name=+DGREDX/redx/datafile/sysaux.268.646333925
datafile 3 switched to datafile copy
input datafile copy RECID=5 STAMP=646334001 file name=+DGREDX/redx/datafile/undotbs1.267.646333989
datafile 4 switched to datafile copy
input datafile copy RECID=6 STAMP=646334001 file name=+DGREDX/redx/datafile/users.266.646333991

contents of Memory Script:
{
set until scn 547574;
recover
clone database
delete archivelog
;
}
executing Memory Script

executing command: SET until clause

Starting recover at 10-FEB-08
allocated channel: ORA_AUX_DISK_1
channel ORA_AUX_DISK_1: SID=148 device type=DISK

starting media recovery

archived log for thread 1 with sequence 7 is already on disk as file +DGREDX/redx/archivelog/2008_02_10/thread_1_seq_7.262.646333999
archived log file name=+DGREDX/redx/archivelog/2008_02_10/thread_1_seq_7.262.646333999 thread=1 sequence=7
media recovery complete, elapsed time: 00:00:01
Finished recover at 10-FEB-08

contents of Memory Script:
{
shutdown clone immediate;
startup clone nomount ;
}
executing Memory Script

database dismounted
Oracle instance shut down

connected to auxiliary database (not started)
Oracle instance started

Total System Global Area 209235968 bytes
Fixed Size 1298920 bytes
Variable Size 71306776 bytes
Database Buffers 134217728 bytes
Redo Buffers 2412544 bytes
sql statement: CREATE CONTROLFILE REUSE SET DATABASE "REDX" RESETLOGS ARCHIVELOG
MAXLOGFILES 16
MAXLOGMEMBERS 3
MAXDATAFILES 100
MAXINSTANCES 8
MAXLOGHISTORY 292
LOGFILE
GROUP 1 ( '+dgredx', '+dgredx' ) SIZE 50 M REUSE,
GROUP 2 ( '+dgredx', '+dgredx' ) SIZE 50 M REUSE,
GROUP 3 ( '+dgredx', '+dgredx' ) SIZE 50 M REUSE
DATAFILE
'+DGREDX/redx/datafile/system.269.646333827'
CHARACTER SET WE8ISO8859P15


contents of Memory Script:
{
set newname for tempfile 1 to
"+dgredx";
switch clone tempfile all;
catalog clone datafilecopy "+DGREDX/redx/datafile/sysaux.268.646333925";
catalog clone datafilecopy "+DGREDX/redx/datafile/undotbs1.267.646333989";
catalog clone datafilecopy "+DGREDX/redx/datafile/users.266.646333991";
switch clone datafile all;
}
executing Memory Script

executing command: SET NEWNAME

renamed tempfile 1 to +dgredx in control file

cataloged datafile copy
datafile copy file name=+DGREDX/redx/datafile/sysaux.268.646333925 RECID=1 STAMP=646334024

cataloged datafile copy
datafile copy file name=+DGREDX/redx/datafile/undotbs1.267.646333989 RECID=2 STAMP=646334024

cataloged datafile copy
datafile copy file name=+DGREDX/redx/datafile/users.266.646333991 RECID=3 STAMP=646334024

datafile 2 switched to datafile copy
input datafile copy RECID=1 STAMP=646334024 file name=+DGREDX/redx/datafile/sysaux.268.646333925
datafile 3 switched to datafile copy
input datafile copy RECID=2 STAMP=646334024 file name=+DGREDX/redx/datafile/undotbs1.267.646333989
datafile 4 switched to datafile copy
input datafile copy RECID=3 STAMP=646334024 file name=+DGREDX/redx/datafile/users.266.646333991

contents of Memory Script:
{
Alter clone database open resetlogs;
}
executing Memory Script

database opened
Finished Duplicate Db at 10-FEB-08

Conclusion

C’est vraiment très simple, non ? D’autant plus que vous pouvez fixer le parallélisme ou les taux d’IO sur les différents canaux et donc réellement maitriser les temps de duplication. Il ne manque peut-être que de compresser pour envoyer par le réseau mais je devine que RMAN nous prépare encore d’autres surprises dans les versions à venir. D’ici là il est toujours possible de déplacer le(s) Disk(s) Group(s) sur le serveur source le temps de constituer le clone.