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.