11g/12c : dataguard - import full tablespace transportable

  • Imprimer

Cet article fait suite à Migration 11g/12c. Il décrit la méthode Migration 11g-12c CDB par Export/Import full par tablespace transportable.

La méthode de migration est proche de celle décrite dans 11g/12c : import full tablespace transportable mais elle fait appel à une dataguard pour éviter l’important downtime qui a lieu lors de la copie des datafiles en read-only de la base source vers la base cible. Evidement si la base source est en 11gR2 cela signifie que la base cible est aussi une 11gR2 tant qu’elle est en standby. Elle sera upgradée après le failover. L’avantage de passer par une dataguard est que pour monter une dataguard, la base source n’a pas besoins d’être arrêtée.

Les caractéristiques de la source et de la cibles sont identiques que dans l’article précédent 11g/12c : import full tablespace transportable, mais il y a un système intermédiaire :

Système source

Système intermédiaire

Système cible

Oracle Database 11.2.0.4 Entreprise Edition

Oracle Database 11.2.0.4 Entreprise Edition

Oracle Database 12.1.0.2 Entreprise Edition

Nom de la base : SHAKA
Unique name : SHAKA

Nom de la base : SHAKA
Unique name : SHAKAMIG

Nom de la pluggable database : PONK
Container : BIGDB

Architecture : standalone

Architecture : standalone

Architecture : standalone CDB

Nom du serveur : oradbm02

Nom du serveur : ora12cdb

Nom du serveur : ora12cdb

Proprio du moteur : oracle

Proprio du moteur : oramig

Proprio du moteur : oracle

OS : Oracle Linux 6.4 64bit

OS : Oracle Linux 6.7 64bit

OS : Oracle Linux 6.7 64bit

 

 

Sur le serveur cible ora12cdb, il y a donc 2 moteurs oracle d’installer. Celui en 12c pour la base cible et mais un moteur 11gR2 pour faire tourner le « clone » de la database de source sur le serveur cible, la standby.

Avant de migrer à proprement parler il faut donc créer notre dataguard. Nous allons passer rapidement sur les concepts de la dataguard (pour plus de détail voir : Dataguard... en gros).

Sur chaque serveur le tnsname.ora doit connaitre le chemin pour joindre les bases distantes :

[oramig@ora12cdb admin]$ cat tnsnames.ora
SHAKA =
(DESCRIPTION =
   (ADDRESS_LIST =
     (ADDRESS = (PROTOCOL = TCP)(Host = oradbm2)(Port = 1521))
   )
(CONNECT_DATA =   (SERVICE_NAME = SHAKA)
)
)

[oraee@oradbm2 admin]$ cat tnsnames.ora
SHAKAMIG =
(DESCRIPTION =
   (ADDRESS_LIST =
     (ADDRESS = (PROTOCOL = TCP)(Host = ora12cdb)(Port = 1521))
   )
(CONNECT_DATA =   (SERVICE_NAME = SHAKAMIG)
)
)

Nous n’oublions pas le force logging sur la primaire :

SQL> alter database force logging;

Un backup full + controlfile for standby :

rman target /
CONFIGURE CONTROLFILE AUTOBACKUP ON;
CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '/oracle/backup/%F';
backup full database format  '/oracle/backup/full%s' plus archivelog format '/oracle/backup/arch%s';
backup format  '/oracle/backup/ctl_sby%s' current controlfile for standby;

(oui nous aurions pu faire à travers le réseau le backup/restore avec un bon DUPLICATE TARGET DATABASE FOR STANDBY etc…une prochaine fois)

Nous générons le pfile à partir de la primaire :

SQL> create pfile='/oracle/backup/initPONK.tmp' from spfile;

Pfile que nous modifions aussitôt pour y mettre les paramétrage de la standby.

*.audit_file_dest='/oracle/oraBase/admin/SHAKA/adump'
*.audit_trail='db'
*.compatible='11.2.0.4.0'
*.control_files='/oracle/oradata/BIGDB/TEMPO/control01.ctl','/oracle/oradata/BIGDB/TEMPO/control02.ctl'
*.db_block_size=8192
*.db_domain=''
*.db_name='SHAKA'
*.diagnostic_dest='/oracle/oraBase'
*.log_archive_dest_1='LOCATION=/oracle/oradata/BIGDB/PONK/arch'
*.open_cursors=300
*.pga_aggregate_target=255852544
*.processes=150
*.remote_login_passwordfile='EXCLUSIVE'
*.sga_target=767557632
*.undo_tablespace='UNDOTBS1'
*.log_archive_config='dg_config=(SHAKA,SHAKAMIG)'
*.log_archive_dest_2='service=SHAKA lgwr async noaffirm valid_for=(online_logfiles,primary_role) db_unique_name=SHAKA'
*.db_unique_name='SHAKAMIG'
*.fal_client='SHAKAMIG'
*.fal_server='SHAKA'
*.db_file_name_convert=('/oradata/SHAKA' '/oracle/oradata/BIGDB/PONK')
*.LOG_FILE_NAME_CONVERT=('/oradata/SHAKA' '/oracle/oradata/BIGDB/PONK')

En rouge les modifications. Ici nous avons utilisé les parameter db_file_name_convert et log_file_name_convert  dans le cas de création de datafile pendant la phase de dataguard pour qu’ils se retrouvent dans l’arborescence de notre futur pluggable database et donc sous BIGDB dans PONK qui sera le nom de notre base en 12c. Car nous allons mettre tous les datafiles dans /oracle/oradata/BIGDB/PONK. Ce n’est pas obligatoire mais pour la démonstration c’est plus propre pour faire une migration dans une architecture CDB en respectant l’arborescence CDB.

Nous copions nos backup, notre pfile et aussi le orapwd de SHAKA sur ora12cdb:

[oraee@oradbm2 dbs]$ scp orapwSHAKA oramig@ora12cdb:/oracle/11.2.0.4/database/dbs
[oraee@oradbm2 backup]$ scp * oramig@ora12cdb:/oracle/backup/

Si nous prévoyons de mettre tous les datafiles de la dataguard dans /oracle/oradata/BIGDB/PONK, il faut aussi prévoir que certains datafiles ne doivent pas s'y trouver comme ceux des tablespaces SYSTEM, SYSAUX et UNDO. Car quand la pluggable database va être crée elle va générer ses propres tablespace SYSTEM, SYSAUX et UNDO et si les datafiles de la dataguard en 11g portent les mêmes noms que ceux de la 12c, il va y avoir un conflit de nom. Nous prévoyons donc  le répertoire /oracle/oradata/BIGDB/TEMPO pour les accueillir le temps de la phase dataguard.

[oracle@ora12cdb ~]$ mkdir -p /oracle/oradata/BIGDB/TEMPO
[oracle@ora12cdb ~]$ chmod g+w /oracle/oradata/BIGDB/TEMPO

Pour la restauration une petite astuce pour générer rapidement le script de restauration alternative:

Sur la primaire :

SQL> SELECT 'SET NEWNAME FOR DATAFILE ' || file# || ' to ''' || name || ''';' FROM V$DATAFILE WHERE status in ('ONLINE','SYSTEM') ORDER BY file#; 

'SETNEWNAMEFORDATAFILE'||FILE#||'TO'''||NAME||''';'
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SET NEWNAME FOR DATAFILE 1 to '/oradata/SHAKA/system01.dbf';
SET NEWNAME FOR DATAFILE 2 to '/oradata/SHAKA/sysaux01.dbf';
SET NEWNAME FOR DATAFILE 3 to '/oradata/SHAKA/undotbs01.dbf';
SET NEWNAME FOR DATAFILE 4 to '/oradata/SHAKA/users01.dbf';
SET NEWNAME FOR DATAFILE 5 to '/oradata/SHAKA/tbs_test_data_01.dbf';
SET NEWNAME FOR DATAFILE 6 to '/oradata/SHAKA/tbs_test_data_02.dbf';
SET NEWNAME FOR DATAFILE 7 to '/oradata/SHAKA/tbs_test_idx_01.dbf';
SET NEWNAME FOR DATAFILE 8 to '/oradata/SHAKA/tbs_image_01.dbf';

Ici il n’y a que 8 datafiles mais quand plus de 1000 cela peut aider. Il suffit de remplacer les chemins. Et de lancer la restauration alterne:

SQL>  startup nomount pfile='/oracle/backup/initPONK.tmp'
RMAN> restore standby controlfile from '/oracle/backup/ctl_sby6';
RMAN> sql 'alter database mount';
run {
SET NEWNAME FOR DATAFILE 1 to '/oracle/oradata/BIGDB/TEMPO/system01.dbf';
SET NEWNAME FOR DATAFILE 2 to '/oracle/oradata/BIGDB/TEMPO/sysaux01.dbf';
SET NEWNAME FOR DATAFILE 3 to '/oracle/oradata/BIGDB/TEMPO/undotbs01.dbf';
SET NEWNAME FOR DATAFILE 4 to '/oracle/oradata/BIGDB/PONK/users01.dbf';
SET NEWNAME FOR DATAFILE 5 to '/oracle/oradata/BIGDB/PONK/tbs_test_data_01.dbf';
SET NEWNAME FOR DATAFILE 6 to '/oracle/oradata/BIGDB/PONK/tbs_test_data_02.dbf';
SET NEWNAME FOR DATAFILE 7 to '/oracle/oradata/BIGDB/PONK/tbs_test_idx_01.dbf';
SET NEWNAME FOR DATAFILE 8 to '/oracle/oradata/BIGDB/PONK/tbs_image_01.dbf';
restore database;
switch datafile all;
recover database;
}

Il ne faut pas ensuite oublier les redo standby si nous voulons faire de l’envoi de redolog pour faire un semblant de temps réel:

ALTER DATABASE ADD STANDBY LOGFILE  '/oracle/oradata/BIGDB/TEMPO/redosby1' size 51200k,
'/oracle/oradata/BIGDB/TEMPO/redosby2' size 51200k,
'/oracle/oradata/BIGDB/TEMPO/redosby3' size 51200k,
'/oracle/oradata/BIGDB/TEMPO/redosby4' size 51200k;

SQL> create spfile from pfile='/oracle/backup/initPONK.tmp';

Il n’est pas obligatoire de créer les redo standby sur la primaire, car il n’est pas prévue de faire de switchover.

Le process de recovery peut être lancé sur la dataguard.

SQL> ALTER DATABASE recover managed standby database using current logfile disconnect from session;

Et pour alimenter ce process, il faut configure la primaire pour qu’elle envoie à la standby de quoi se nourrir (pas de downtime):

alter system set standby_file_management=AUTO scope=both;
alter system set log_archive_config='dg_config=(SHAKA,SHAKAMIG)' scope=both;
alter system set log_archive_dest_2='service=SHAKAMIG lgwr async noaffirm valid_for=(online_logfiles,primary_role) db_unique_name=SHAKAMIG' scope=both;
alter system set fal_client='SHAKA' scope=both;
alter system set fal_server='SHAKAMIG' scope=both;

Puis le jour J arrive, la migration vers la 12c doit avoir lieu.

Nous vérifions que les 2 bases sont bien synchro après avoir arrêté les applications :

select instance_name, host_name,DATABASE_ROLE,current_scn,scn_to_timestamp(current_scn) from v$database, v$instance;
-- sur la primaire
INSTANCE_NAME           HOST_NAME          DATABASE_ROLE    CURRENT_SCN SCN_TO_TIMESTAMP(CURRENT_SCN)
---------------- -------------------- ---------------- ----------- ---------------------------------------------------------------------------
SHAKA                 oradbm2.localdomain  PRIMARY                               2211670 13-OCT-15 09.31.14.000000000 PM

-- sur la standby
INSTANCE_NAME           HOST_NAME          DATABASE_ROLE    CURRENT_SCN SCN_TO_TIMESTAMP(CURRENT_SCN)
---------------- -------------------- ---------------- ----------- ---------------------------------------------------------------------------
SHAKA                 ora12cdb.localdomain PHYSICAL STANDBY           2211670 13-OCT-15 09.31.13.000000000 PM

Nous arrêtons la primaire:

SQL> shutdown immediate

Et nous lançons le failover sur la standby:

SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE FINISH;
Database altered.

SQL> ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY;
Database altered.

SQL> startup force;

Maintenant notre  base primaire est sur le moteur oracle 11.2.0.4 qui est sur le serveur où se trouve notre CDB en 12.1.0.2.

Tous les datafiles se trouvent bien là où nous voulions :

SQL> select FILE_NAME from dba_data_files;
FILE_NAME
--------------------------------------------------------------------------------
/oracle/oradata/BIGDB/TEMPO/system01.dbf
/oracle/oradata/BIGDB/TEMPO/sysaux01.dbf
/oracle/oradata/BIGDB/TEMPO/undotbs01.dbf
/oracle/oradata/BIGDB/PONK/users01.dbf
/oracle/oradata/BIGDB/PONK/tbs_test_data_01.dbf
/oracle/oradata/BIGDB/PONK/tbs_test_data_02.dbf
/oracle/oradata/BIGDB/PONK/tbs_test_idx_01.dbf
/oracle/oradata/BIGDB/PONK/tbs_image_01.dbf

Il faut faire attention au tempfile qui comme les datafiles des tablespace SYSTEM, SYSAUX et UNDO peuvent rentrer en conflit avec les nouveaux tempfile :

SQL> select FILE_NAME from dba_temp_files;
FILE_NAME
--------------------------------------------------------------------------------
/oracle/oradata/BIGDB/PONK/temp01.dbf

Nous allons donc créer un nouveau tempfile ailleurs et supprimer l’ancien:

SQL>ALTER TABLESPACE TEMP ADD TEMPFILE '/oracle/oradata/BIGDB/TEMPO/temp02.dbf' size 1g;
SQL>ALTER DATABASE TEMPFILE '/oracle/oradata/BIGDB/PONK/temp01.dbf' DROP INCLUDING DATAFILES;

Plus rien n’empêche la création de notre nouvelle pluggable database. La création se fait simplement par clonage de la PDB$SEED :

SQL> show pdbs
    CON_ID CON_NAME                                  OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
                 2 PDB$SEED                                        READ ONLY  NO

SQL> alter session set pdb_file_name_convert='/oracle/oradata/BIGDB/pdbseed','/oracle/oradata/BIGDB/PONK';
Session altered.

SQL> create pluggable database PONK admin user goz identified by goz;
Pluggable database created.

La nouvelle base PONK est créé mais pour l’instant elle est vide, elle attend impatiemment les données à migrer qui sont d’ailleurs déjà sur le serveur ora12cdb mais dans le moteur 11gR2.

Comme dans la migration export/import full par transportable tablespace (11g/12c : import full tablespace transportable), nous créons un dblink dans PONK qui pointe vers SHAKA :

[oracle@ora12cdb admin]$ cat tnsnames.ora
SHAKA =
(DESCRIPTION =
   (ADDRESS_LIST =
     (ADDRESS = (PROTOCOL = TCP)(Host = ora12cdb)(Port = 1521))
   )
(CONNECT_DATA =
   (SERVICE_NAME = SHAKAMIG)
)
)

Pourquoi SHAKAMIG pour le service name et pas SHAKA, tous simplement parce que la base SHAKA sur le serveur ora12cdb a pour unique_name SHAKAMIG, héritage de sa vie antérieure de dataguard.

SQL> alter session set container=PONK;
SQL> alter pluggable database PONK open;
SQL> ! mkdir /oracle/dumpmig
SQL> create directory dir_dump_mig as '/oracle/dumpmig';
SQL> grant read, write on directory dir_dump_mig to system;
SQL> create public database link SHAKA_LINK connect to system identified by oracle using 'SHAKA';
SQL> select owner, tablespace_name , sum(bytes)/1024/1024 from dba_segments group by owner, tablespace_name order by  1,2
OWNER                   TABLESPACE_NAME                SUM(BYTES)/1024/1024
------------------------------ --------------------
APPQOSSYS              SYSAUX                               .25
DBSNMP                    SYSAUX                              1.5
OUTLN                      SYSTEM                              .5625
SYS                          SYSAUX                               62.375
SYS                          SYSTEM                               255.0625
SYS                          UNDOTBS1                           562.6875
SYSTEM                    SYSAUX                               14.8125
SYSTEM                    SYSTEM                              15.875
U_TEST                    TBS_IMAGE                          88.9375
U_TEST                    TBS_TEST_DATA                  118
U_TEST                    TBS_TEST_IDX                      272.1875
WMSYS                     SYSAUX                               7.5

Sur la base SHAKA en 11gR2, nous mettons en read-only tous les tablespaces.

[oramig@ora12cdb ~]$ sqlplus / as sysdba
alter tablespace TBS_IMAGE read only;
alter tablespace TBS_TEST_DATA read only;
alter tablespace TBS_TEST_IDX read only;
alter tablespace USERS read only;

Read-only cela signifie entre autre que le moteur de la 11gR2 doit avoir au moins le droit read sur les fichiers donc le user oramig doit avoir read sur les fichiers, et comme on veut que ces datafiles appartiennent à la 12c soit ici le user linux oracle, nous pouvons dore et déjà faire le switch de user sur les fichiers :

chown oracle.oinstall /oracle/oradata/BIGDB/PONK/tbs_image_01.dbf
chown oracle.oinstall /oracle/oradata/BIGDB/PONK/tbs_test_data_01.dbf
chown oracle.oinstall /oracle/oradata/BIGDB/PONK/tbs_test_data_02.dbf
chown oracle.oinstall /oracle/oradata/BIGDB/PONK/tbs_test_idx_01.dbf
chown oracle.oinstall /oracle/oradata/BIGDB/PONK/users01.dbf

Puis à partir de l’environnement 12c nous lançons l’export/import full transportable tablespace (comme dans 11g/12c : import full tablespace transportable):

[oracle@ora12cdb ~]$ vi migration.par
network_link=SHAKA_LINK
version=12
full=y
transportable=always
metrics=y
exclude=statistics
logfile=dir_dump_mig:migration.log
transport_datafiles='/oracle/oradata/BIGDB/PONK/users01.dbf','/oracle/oradata/BIGDB/PONK/tbs_test_data_01.dbf','/oracle/oradata/BIGDB/PONK/tbs_test_data_02.dbf','/oracle/oradata/BIGDB/PONK/tbs_test_idx_01.dbf','/oracle/oradata/BIGDB/PONK/tbs_image_01.dbf'

[oracle@ora12cdb ~]$ impdp system/oracle@PONK parfile=migration.par

La base SHAKA peut être définitivement stoppée.

Après l’import c’est fini… presque… avant de faire repartir la production, il faut mettre les tablespaces importés en read write, cela permet aussi de mettre à jour les entêtes qui contiennent toujours les anciennes références vers feu SHAKA, car dorénavant c’est PONK :

alter tablespace TBS_IMAGE read write;
alter tablespace TBS_TEST_DATA read write;
alter tablespace TBS_TEST_IDX read write;
alter tablespace USERS read write;

Même si la production peut reprendre à ce moment-là, il est bien de faire le ménage juste avant. Tous les datafiles et controlfiles appartenant encore à  SHAKA sur le serveur ora12c doivent être supprimés :

[root@ora12cdb BIGDB]# rm -fr /oracle/oradata/BIGDB/TEMPO/

Cette méthode est bien sûr un peu complexe, elle mêle plusieurs compétences : dataguard, export/import transportable tablespace mais le gros avantage est un temps de downtime minime, la migration/copie des data est faite à chaud lors de l’installation de la dataguard.

Le downtime correspond au failover + export/import full transportable tablespace (il n’y a que des métadonnées qui sont exportées et importées) + quelques commandes annexes instantanées en temps d’exécution (le plus long est la préparation en amont).

Il y a donc quand même un downtime, petit downtime mais downtime quand même… est-il possible de ne pas avoir de downtime ?... oui mais cette fois il faut mettre en œuvre une autre technologie : GoldenGate.

 

{jcomments on}