Database PITR et création/suppression de fichiers

Un scénario qui n’est pas spécialement bien décrit dans la documentation est celui ou vous faites un ADD ou un DROP d’un fichier de données, via une commande sur le tablespace et que, pour une obscure raison, vous décidez d’effectuer un point in time recovery (PITR) de votre base de données. Oui obscure au moins pour le DROP puisque, dans ce cas, effectuer l’opération pour un tablespace (TSPITR) est peut-être plus adapté.

Ajout d’un fichier…

Dans ce cas, à condition que les SCN des fichiers restaurés précédent la création du fichier et donc que l’ordre d’ajout du datafile soit dans les fichier de logs que vous allez appliquer, il n’y a rien à considérer. En effet, même si le fichier est référencé dans le fichier de contrôle courant, le SCN de création l’est aussi. Vous pouvez d’ailleurs visualiser cet information en interrogeant V$DATAFILE lorsque l’instance est montée (cf CREATION_CHANGE#).

La base Oracle pourra donc être ouverte en mode RESETLOGS même si le fichier n’est pas encore créé mais qu’il est référencé dans le fichier de contrôle courant. Voici un exemple ou vous faites un PITR avant la création du tablespace DEMO2 :

SQL> create restore point z;

SQL> create tablespace demo2
datafile size 20M;

Utilisez ensuite RMAN pour faire le recover de votre base de données avant la création du fichier :

RMAN> startup force mount;

Oracle instance started
database mounted

Total System Global Area 313860096 bytes

Fixed Size 1299624 bytes
Variable Size 268438360 bytes
Database Buffers 37748736 bytes
Redo Buffers 6373376 bytes

RMAN> restore database;

Starting restore at 10-APR-08
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=152 device type=DISK

creating datafile file number=6 name=+DGBLUJ/bluj/datafile/demo2.262.651679255
channel ORA_DISK_1: starting datafile backup set restore
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_DISK_1: restoring datafile 00001 to +DGBLUJ/bluj/datafile/system.266.651365655
channel ORA_DISK_1: restoring datafile 00002 to +DGBLUJ/bluj/datafile/sysaux.267.651365659
channel ORA_DISK_1: restoring datafile 00003 to +DGBLUJ/bluj/datafile/undotbs1.256.651365661
channel ORA_DISK_1: restoring datafile 00004 to +DGBLUJ/bluj/datafile/users.257.651365659
channel ORA_DISK_1: restoring datafile 00005 to +DGBLUJ/bluj/datafile/demo.263.651678757
channel ORA_DISK_1: reading from backup piece /u01/app/oracle/flash_recovery_area/BLUJ/backupset/2008_04_10/o1_mf_nnndf_TAG20080410T132249_3zwm7mln_.bkp
channel ORA_DISK_1: piece handle=/u01/app/oracle/flash_recovery_area/BLUJ/backupset/2008_04_10/o1_mf_nnndf_TAG20080410T132249_3zwm7mln_.bkp tag=TAG20080410T132249
channel ORA_DISK_1: restored backup piece 1
channel ORA_DISK_1: restore complete, elapsed time: 00:01:35
Finished restore at 10-APR-08

RMAN> recover database until restore point z;

Starting recover at 10-APR-08
using channel ORA_DISK_1

starting media recovery

archived log for thread 1 with sequence 9 is already on disk as file /u01/app/oracle/flash_recovery_area/BLUJ/archivelog/2008_04_10/o1_mf_1_9_3zwml9fz_.arc
archived log for thread 1 with sequence 10 is already on disk as file /u01/app/oracle/flash_recovery_area/BLUJ/archivelog/2008_04_10/o1_mf_1_10_3zwmlj64_.arc
archived log for thread 1 with sequence 11 is already on disk as file /u01/app/oracle/flash_recovery_area/BLUJ/archivelog/2008_04_10/o1_mf_1_11_3zwmmx5t_.arc
archived log for thread 1 with sequence 1 is already on disk as file /u01/app/oracle/flash_recovery_area/BLUJ/archivelog/2008_04_10/o1_mf_1_1_3zwnwgng_.arc
channel ORA_DISK_1: starting archived log restore to default destination
channel ORA_DISK_1: restoring archived log
archived log thread=1 sequence=8
channel ORA_DISK_1: reading from backup piece /u01/app/oracle/flash_recovery_area/BLUJ/backupset/2008_04_10/o1_mf_annnn_TAG20080410T132456_3zwmcn8r_.bkp
channel ORA_DISK_1: piece handle=/u01/app/oracle/flash_recovery_area/BLUJ/backupset/2008_04_10/o1_mf_annnn_TAG20080410T132456_3zwmcn8r_.bkp tag=TAG20080410T132456
channel ORA_DISK_1: restored backup piece 1
channel ORA_DISK_1: restore complete, elapsed time: 00:00:01
archived log file name=/u01/app/oracle/flash_recovery_area/BLUJ/archivelog/2008_04_10/o1_mf_1_8_3zwoogbq_.arc thread=1 sequence=8
channel default: deleting archived log(s)
archived log file name=/u01/app/oracle/flash_recovery_area/BLUJ/archivelog/2008_04_10/o1_mf_1_8_3zwoogbq_.arc RECID=25 STAMP=651679470
archived log file name=/u01/app/oracle/flash_recovery_area/BLUJ/archivelog/2008_04_10/o1_mf_1_9_3zwml9fz_.arc thread=1 sequence=9
archived log file name=/u01/app/oracle/flash_recovery_area/BLUJ/archivelog/2008_04_10/o1_mf_1_10_3zwmlj64_.arc thread=1 sequence=10
archived log file name=/u01/app/oracle/flash_recovery_area/BLUJ/archivelog/2008_04_10/o1_mf_1_11_3zwmmx5t_.arc thread=1 sequence=11
archived log file name=/u01/app/oracle/flash_recovery_area/BLUJ/archivelog/2008_04_10/o1_mf_1_1_3zwnwgng_.arc thread=1 sequence=1
media recovery complete, elapsed time: 00:00:02
Finished recover at 10-APR-08

RMAN> alter database open resetlogs;

database opened

Vous remarquez d’Oracle recrée le fichier associé au tablespace DEMO2 (Ligne en rouge), et qu’il n’y a ensuite aucun problème pour ouvrir la base de données. Un SELECT sur V$DATAFILE après l’ouverture de la base de données vous confirmera que le fichier a été supprimé.

Suppression d’un fichier…

Ce second cas est un peu plus compliqué, en effet, si le fichier est dans une sauvegarde et qu’il n’est plus dans le fichier de contrôle courant, Oracle ne peut pas le restaurer simplement. D’autre part, utiliser le fichier de backup du fichier de contrôle après la sauvegarde de la base de données a plusieurs inconvénients. Les backup des archivelogs en particulier peuvent ne être pas dans ce fichier et retrouver les morceaux peut devenir un vrai casse-tête. C’est surtout vrai avec des sauvegardes sur bandes. Bien sur, si vous avez un catalogue RMAN tous ça est sans objets… Enfin, le plus simple est sans doute de partir du « current » controlfile et de restaurer votre base de données jusqu’au moment désiré :

SQL> create restore point x;

Restore point created.

SQL> drop tablespace demo
including contents;

Tablespace dropped.

SQL> startup force mount;

ORACLE instance started.

Total System Global Area 313860096 bytes
Fixed Size 1299624 bytes
Variable Size 268438360 bytes
Database Buffers 37748736 bytes
Redo Buffers 6373376 bytes
Database mounted.
SQL> exit;

$ rman target /

Recovery Manager: Release 11.1.0.6.0 - Production on Thu Apr 10 21:35:00 2008

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

connected to target database: BLUJ (DBID=1975191514, not open)

RMAN> restore database;

Starting restore at 10-APR-08
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=150 device type=DISK

channel ORA_DISK_1: starting datafile backup set restore
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_DISK_1: restoring datafile 00001 to +DGBLUJ/bluj/datafile/system.266.651365655
channel ORA_DISK_1: restoring datafile 00002 to +DGBLUJ/bluj/datafile/sysaux.267.651365659
channel ORA_DISK_1: restoring datafile 00003 to +DGBLUJ/bluj/datafile/undotbs1.256.651365661
channel ORA_DISK_1: restoring datafile 00004 to +DGBLUJ/bluj/datafile/users.257.651365659
channel ORA_DISK_1: reading from backup piece /u01/app/oracle/flash_recovery_area/BLUJ/backupset/2008_04_10/o1_mf_nnndf_TAG20080410T212937_3zxhrc1p_.bkp

channel ORA_DISK_1: piece handle=/u01/app/oracle/flash_recovery_area/BLUJ/backupset/2008_04_10/o1_mf_nnndf_TAG20080410T212937_3zxhrc1p_.bkp tag=TAG20080410T212937
channel ORA_DISK_1: restored backup piece 1
channel ORA_DISK_1: restore complete, elapsed time: 00:01:45
Finished restore at 10-APR-08

RMAN> recover database until restore point x;

Starting recover at 10-APR-08
using channel ORA_DISK_1

starting media recovery
media recovery complete, elapsed time: 00:00:01

Finished recover at 10-APR-08

RMAN> exit

Vous noterez que si vous interrogez V$DATAFILE avant l’open RESETLOGS le fichier manquant n’est pas référencé (Ce qui est logique puisqu’il a été supprime du current controlfile). En revanche, après l’open RESETLOGS, Oracle, sait qu’il y avait un fichier ; il l’a reconstruit grâce à son dictionnaire.

SQL> col name format a80
SQL> set lines 120
SQL> select file#, name
from v$datafile;

FILE# NAME
----- ------------------------------------------------
1 +DGBLUJ/bluj/datafile/system.266.651365655
2 +DGBLUJ/bluj/datafile/sysaux.267.651365659
3 +DGBLUJ/bluj/datafile/undotbs1.256.651365661
4 +DGBLUJ/bluj/datafile/users.257.651365659

SQL> alter database open resetlogs;

Database altered.

SQL> select file#, name
from v$datafile;
FILE# NAME
----- ------------------------------------------------------
1 +DGBLUJ/bluj/datafile/system.266.651365655
2 +DGBLUJ/bluj/datafile/sysaux.267.651365659
3 +DGBLUJ/bluj/datafile/undotbs1.256.651365661
4 +DGBLUJ/bluj/datafile/users.257.651365659
5 /u01/app/oracle/product/11.1.0/db_1/dbs/MISSING00005

SQL> exit

Maintenant que vous avez une référence au fichier et s’il est dans une sauvegarde, le restaurer et en faire le recover à partir de 10g devient un jeu d’enfant. Il faut simplement que vous décidiez du nom (ou de la destination en OMF) du fichier en positionnant le NEWNAME come ci-dessous :

RMAN> run
{
set newname for datafile 5 to '+dgbluj';
restore datafile 5;
switch datafile all;
}

executing command: SET NEWNAME
using target database control file instead of recovery catalog

Starting restore at 10-APR-08
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=150 device type=DISK

channel ORA_DISK_1: starting datafile backup set restore
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_DISK_1: restoring datafile 00005 to +DGBLUJ
channel ORA_DISK_1: reading from backup piece /u01/app/oracle/flash_recovery_area/BLUJ/backupset/2008_04_10/o1_mf_nnndf_TAG20080410T212937_3zxhrc1p_.bkp
channel ORA_DISK_1: piece handle=/u01/app/oracle/flash_recovery_area/BLUJ/backupset/2008_04_10/o1_mf_nnndf_TAG20080410T212937_3zxhrc1p_.bkp tag=TAG20080410T212937
channel ORA_DISK_1: restored backup piece 1
channel ORA_DISK_1: restore complete, elapsed time: 00:00:01
Finished restore at 10-APR-08

datafile 5 switched to datafile copy
input datafile copy RECID=6 STAMP=651707407 file name=+DGBLUJ/bluj/datafile/demo.263.651707407

Et voila… reste à faire le recover, ce qui est autoatiquement fait jusqu’au SCN de l’open RESETLOGS puisque cette information relative à la dernière incarnation de votre base de données est dans le fichier de contrôle. Vous pourrez ensuite passer le fichier de données ONLINE :

RMAN> recover datafile 5;

Starting recover at 10-APR-08
using channel ORA_DISK_1

starting media recovery

archived log for thread 1 with sequence 4 is already on disk as file /u01/app/oracle/flash_recovery_area/BLUJ/archivelog/2008_04_10/o1_mf_1_4_3zxjowz4_.arc
channel ORA_DISK_1: starting archived log restore to default destination
channel ORA_DISK_1: restoring archived log
archived log thread=1 sequence=3
channel ORA_DISK_1: reading from backup piece /u01/app/oracle/flash_recovery_area/BLUJ/backupset/2008_04_10/o1_mf_annnn_TAG20080410T213132_3zxhvx9b_.bkp
channel ORA_DISK_1: piece handle=/u01/app/oracle/flash_recovery_area/BLUJ/backupset/2008_04_10/o1_mf_annnn_TAG20080410T213132_3zxhvx9b_.bkp tag=TAG20080410T213132
channel ORA_DISK_1: restored backup piece 1
channel ORA_DISK_1: restore complete, elapsed time: 00:00:01
archived log file name=/u01/app/oracle/flash_recovery_area/BLUJ/archivelog/2008_04_10/o1_mf_1_3_3zxjzqof_.arc thread=1 sequence=3
channel default: deleting archived log(s)
archived log file name=/u01/app/oracle/flash_recovery_area/BLUJ/archivelog/2008_04_10/o1_mf_1_3_3zxjzqof_.arc RECID=36 STAMP=651707447
archived log file name=/u01/app/oracle/flash_recovery_area/BLUJ/archivelog/2008_04_10/o1_mf_1_4_3zxjowz4_.arc thread=1 sequence=4
media recovery complete, elapsed time: 00:00:00
Finished recover at 10-APR-08

RMAN> sql 'alter database datafile 5 online';

sql statement: alter database datafile 5 online

L’inconvénient toutefois d’une telle approche est que si vous avez beaucoup d’archive logs à rejouer, il faut le faire 2 fois… Peut-être la solution après tout, c’est de faire attention à ce que vous supprimez ! Quoique, si vous lisez ce post, c’est peut-être à cause de quelqu’un d’autre.