22 Novembre 2017
Si comme moi vous allez trop vite à faire du "DROP pluggable database" en masse, ou plutôt du "rm -rf" sur des répertoires liés à des anciennes pluggables et que par inadvertance le répertoire de la pluggable modèle "PDB$SEED" est supprimé, alors cet article est fait pour vous !
Dans mon cas, j'ai supprimé involontairement (et au final tant mieux, cela me permet de rédiger ce petit article) le répertoire de la pluggable database "PDB$SEED", empêchant ainsi son ouverture en READ ONLY et de facto la création de nouvelles PDB....
SQL> alter pluggable database PDB$SEED open read only; alter pluggable database PDB$SEED open read only * ERROR at line 1: ORA-01157: cannot identify/lock data file 6 - see DBWR trace file ORA-01110: data file 6: '/oradata/CDBORA1/5D8F188ABB451742E0537338A8C06BF3/datafile/o1_mf_undotbs1_f08vl0cn_.dbf'
Mais ce n'est jamais grave avec Oracle, on peut toujours (ou presque) réparer ce qu'on a cassé !
Pour retrouver ma pluggable modèle PDB$SEED, comme je n'ai pas de backup RMAN je vais utiliser une autre base container en 12.2 sur laquelle je n'ai pas fait de boulettes, en utilisant un dblink.
Sur ma base "CDBORA1" (celle qui est cassée) je crée un dblink qui va pointer sur ma container source "CDBORA2" en utilisant le user "system" :
SQL> create database link ausecours connect to system identified by oracle using 'CDBORA2'; Database link created.
Une vérification pour s'assurer que ce dblink soit bien fonctionnel :
SQL> select name,cdb from v$database@ausecours; NAME CDB --------- --- CDBORA2 YES SQL> select con_id,name,open_mode from v$pdbs@ausecours where name='PDB$SEED'; CON_ID NAME OPEN_MODE ---------- --------------- ---------- 2 PDB$SEED READ ONLY
Ok, je vais maintenant générer un fichier XML contenant les métadatas (structure) de la pluggable PDB$SEED, toujours en restant connecté sur ma container database cassée en passant par le DBLINK.
SQL> exec DBMS_PDB.DESCRIBE(pdb_descr_file => '/home/oracle/pdbseed.xml',pdb_name=>'pdb$seed@ausecours'); PL/SQL procedure successfully completed.
Un petit check :
SQL> !ls -ltr /home/oracle/pdbseed.xml -rw-r--r-- 1 oracle dba 6287 Nov 21 17:48 /home/oracle/pdbseed.xml
Maintenant, je vais copier les fichiers / datafiles de la pluggable PDB$SEED de la container source CDBORA2 vers la base container cassée CDBORA1 en prenant soin au préalable de les recenser :
SQL> select name from v$datafile@ausecours where con_id=2; NAME -------------------------------------------------------------------------------- /oradata/CDBORA2/5E8116B0F3EA2C31E0537338A8C0C791/datafile/o1_mf_system_f18ljz44_.dbf /oradata/CDBORA2/5E8116B0F3EA2C31E0537338A8C0C791/datafile/o1_mf_sysaux_f18lkgpq_.dbf /oradata/CDBORA2/5E8116B0F3EA2C31E0537338A8C0C791/datafile/o1_mf_undotbs1_f18lkngd_.dbf SQL> select name from v$tempfile@ausecours where con_id=2; NAME -------------------------------------------------------------------------------- /oradata/CDBORA2/5E8116B0F3EA2C31E0537338A8C0C791/datafile/o1_mf_temp_f18lko8d_.tmp
La base modèle PDB$SEED etant en READ ONLY je peux sans problème effectuer ma copie de fichier vers l'arborescence de la container db casssée CDBORA1
[SRVORA]<oracle>/oracle[]:mkdir /oradata/CDBORA1/pdbseed [SRVORA]<oracle>/oracle[]:mkdir /oradata/CDBORA1/pdbseed/datafile [SRVORA]<oracle>/oracle[]:cp -p /oradata/CDBORA2/5E8116B0F3EA2C31E0537338A8C0C791/datafile/o1_mf_system_f18ljz44_.dbf /oradata/CDBORA1/pdbseed/datafile/. [SRVORA]<oracle>/oracle[]:cp -p /oradata/CDBORA2/5E8116B0F3EA2C31E0537338A8C0C791/datafile/o1_mf_sysaux_f18lkgpq_.dbf /oradata/CDBORA1/pdbseed/datafile/. [SRVORA]<oracle>/oracle[]:cp -p /oradata/CDBORA2/5E8116B0F3EA2C31E0537338A8C0C791/datafile/o1_mf_undotbs1_f18lkngd_.dbf /oradata/CDBORA1/pdbseed/datafile/. [SRVORA]<oracle>/oracle[]:cp -p /oradata/CDBORA2/5E8116B0F3EA2C31E0537338A8C0C791/datafile/o1_mf_temp_f18lko8d_.tmp /oradata/CDBORA1/pdbseed/datafile/.
Je peux maintenant réintégrer ces fichiers sur ma container cible (CDBORA1) dans une nouvelle pluggable PDB$SEED, mais il me faut auparavant supprimer l'ancienne qui est inutilisable :
SQL> show pdbs CON_ID CON_NAME OPEN MODE RESTRICTED ---------- ------------------------------ ---------- ---------- 2 PDB$SEED MOUNTED SQL> drop pluggable database PDB$SEED including datafiles; drop pluggable database PDB$SEED including datafiles * ERROR at line 1: ORA-65017: seed pluggable database may not be dropped or altered
Pour dropper cette pluggable particulière, il faut fixer le paramètre "_oracle_script" à true :
SQL> alter session set "_oracle_script"=true; Session altered. SQL> alter pluggable database PDB$SEED close immediate ; alter pluggable database PDB$SEED close immediate * ERROR at line 1: ORA-65020: pluggable database PDB$SEED already closed SQL> drop pluggable database PDB$SEED including datafiles; Pluggable database dropped.
Et maintenant je la recréée toute propre :
SQL> create pluggable database "pdb$seed" using '/home/oracle/pdbseed.xml' source_file_name_convert=('/oradata/CDBORA2/5E8116B0F3EA2C31E0537338A8C0C791','/oradata/CDBORA1/pdbseed') nocopy tempfile reuse; Pluggable database created.
On valide que cette pluggable soit MOUNTED, et nous allons l'ouvrir en READ ONLY :
SQL> alter pluggable database PDB$SEED open read only; alter pluggable database PDB$SEED open read only * ERROR at line 1: ORA-65085: cannot open pluggable database in read-only mode
Pas de chance, il n'est pas possible d'ouvrir directement en read only la pluggable, tout simplement car avant cela elle doit être synchronisée avec le dictionnaire de données de la container DB.
Je vais donc l'ouvrir en READ WRITE, pour ensuite la remettre en READ ONLY :
SQL> alter pluggable database PDB$SEED open read write; Pluggable database altered. SQL> alter pluggable database PDB$SEED close ; Pluggable database altered. SQL> alter pluggable database PDB$SEED open read only; Pluggable database altered.
Une petite vérification, et je replace le paramètre caché "_oracle_script" à false pour terminer les actions :
SQL> alter pluggable database PDB$SEED open read only; Pluggable database altered. SQL> show pdbs CON_ID CON_NAME OPEN MODE RESTRICTED ---------- ------------------------------ ---------- ---------- 2 PDB$SEED READ ONLY NO SQL> alter session set "_oracle_script"=false; Session altered.
Et voilà comment il est possible de récupérer la Pluggable DB "modèle" après une jolie erreur humaine, sans aucun backup RMAN !