RMAN : VALIDATE vérifier si des blocs sont corrompus - VALIDATE check if blocks are corrupted
Introduction
Dans un article précédent nous avons vu la commande CROSSCHECK de RMAN qui vérifie que les backups du repository RMAN sont toujours présents sur le disque dur (même nom, même répertoire).
Aujourd'hui voyons la commande VALIDATE : elle vérifie si des fichiers (datafiles, backupsets, redologs, spfile, ctrl file etc) sont corrompus ou manquants.
Points d'attention
N/A.
Base de tests
Une base Oracle 18c multi-tenants.
Exemples
============================================================================================
Les corruptions
============================================================================================
Oracle utilise trois fonctions VALIDATE : ne vous inquiétez pas, quand vous l'utilisez avec BACKUP ou RESTORE, à aucun moment Oracle ne fait de sauvegarde ou de restauration.
- VALIDATE : effectue les mêmes types de contrôles que BACKUP VALIDATE mais Oracle peut vérifier une plus grande sélection d'objets
- BACKUP ... VALIDATE : valider les blocs des backupsets
- RESTORE ... VALIDATE : valider les blocs des backupsets qui seront utilisés pour un RESTORE
Un bloc corrompu est un bloc dont le contenu est différent de celui attendu par Oracle. Il y a deux types de corruption : physique et logique. Par défaut la commande VALIDATE ne détecte que les corruptions physiques, pas les logiques.
Corruption physique ou media corruption
La base ne reconnait pas du tout le bloc de données ou le checksum est invalide ou le bloc ne contient que des zéros ou bien il y a incohérence entre le header et le footer.
- pb lié aux disques durs ou aux contrôleurs de disques
- pb de mémoire
- pb lié à un bug du logiciel Oracle
- ...
Corruption logique
Le contenu du bloc est logiquement incohérent : par exemple la corruption d'un enregistrement ou d'une entrée d'index. Selon AskTom il est plus ardu à simuler car il faut créer un bloc Oracle de structure valide MAIS avec des données incorrectes; et pour cela il faut utiliser un éditeur hexadécimal et connaître la structure d'un bloc Oracle; on ne testera donc pas ce cas car trop complexe à implémenter!
Par défaut, VALIDATE ne teste pas la corruption logique, il faut le demander explicitement avec le mot clé LOGICAL.
La commande VALIDATE met à jour les vues suivantes chaque fois qu'elle rencontre un bloc corrompu
- V$BACKUP_CORRUPTION et V$COPY_CORRUPTION : blocs corrompus dans les backups RMAN, pas dans le base elle même
- V$DATABASE_BLOCK_CORRUPTION : blocs corrompus dans la base et non pas dans les backups RMAN
Dans V$BACKUP_CORRUPTION, voici les types de corruption répertoriés
- ALL ZERO - Block header on disk contained only zeros. The block may be valid if it was never filled and if it is in an Oracle7 file. The buffer will be reformatted to the Oracle8 standard for an empty block.
- FRACTURED - Block header looks reasonable, but the front and back of the block are different versions.
- CHECKSUM - optional check value shows that the block is not self-consistent. It is impossible to determine exactly why the check value fails, but it probably fails because sectors in the middle of the block are from different versions.
- CORRUPT - Block is wrongly identified or is not a data block (for example, the data block address is missing)
- LOGICAL - Block is logically corrupt
- NOLOGGING - Block does not have redo log entries (for example, NOLOGGING operations on primary database can introduce this type of corruption on a physical standby)
Dans V$DATABASE_BLOCK_CORRUPTION les types d'erreurs loggués sont les mêmes que dans V$BACKUP_CORRUPTION sauf NOLOGGING qui est absent.
Une fois les blocs corrompus identifiés, il faut utiliser l'outil "Block Media Recovery" de RMAN pour corriger le problème.
============================================================================================
Base de test
============================================================================================
J'utilise un backup du tablespace CROSS pour mes tests.
[oracle@vbgeneric ~]$ rman target SYS@orcl
connected to target database: ORCL12C:ORCL (DBID=2846920952)
RMAN> list backup of tablespace CROSS;
using target database control file instead of recovery catalog
List of Backup Sets
===================
BS Key Type LV Size Device Type Elapsed Time Completion Time
------- ---- -- ---------- ----------- ------------ ---------------
2 Full 1.04M DISK 00:00:00 31-JAN-21
BP Key: 2 Status: AVAILABLE Compressed: NO Tag: TAG20210131T094819
Piece Name: /u01/app/oracle/fast_recovery_area/orcl12c/ORCL12C/49BFF8A6BB912582E0530100007F8BE4/backupset/2021_01_31/o1_mf_nnndf_TAG20210131T094819_j1fjsn5j_.bkp
List of Datafiles in backup set 2
File LV Type Ckp SCN Ckp Time Abs Fuz SCN Sparse Name
---- -- ---- ---------- --------- ----------- ------ ----
21 Full 2074043 31-JAN-21 NO /u01/app/oracle/oradata/orcl12c/orcl/cross.dbf
VALIDATE d'un datafile
Si je fais un VALIDATE sur le tablespace CROSS, Oracle vérifie bien le datafile du tbs mais pas son backupset.
On voit dans la sortie que les colonnes "Marked Corrupt" et "Blocks Failing" valent 0 : excellent!
RMAN> validate tablespace CROSS;
Starting validate at 06-FEB-21
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=42 device type=DISK
channel ORA_DISK_1: starting validation of datafile
channel ORA_DISK_1: specifying datafile(s) for validation
input datafile file number=00021 name=/u01/app/oracle/oradata/orcl12c/orcl/cross.dbf
channel ORA_DISK_1: validation complete, elapsed time: 00:00:01
List of Datafiles
=================
File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
21 OK 0 12673 12800 2073514
File Name: /u01/app/oracle/oradata/orcl12c/orcl/cross.dbf
Block Type Blocks Failing Blocks Processed
---------- -------------- ----------------
Data 0 0
Index 0 0
Other 0 127
Finished validate at 06-FEB-21
VALIDATE d'un backupset
Pour valider le backupset de ce tablespace, il faut utiliser le numéro du backupset. A noter que la sortie n'a rien à voir avec celle du VALIDATE du tablespace ci-dessus. Oracle ne détecte aucune erreur et on a "validation complete" donc le VALDATE a bien eu lieu.
RMAN> validate backupset 2;
Starting validate at 06-FEB-21
using channel ORA_DISK_1
channel ORA_DISK_1: starting validation of datafile backup set
channel ORA_DISK_1: reading from backup piece /u01/app/oracle/fast_recovery_area/orcl12c/ORCL12C/49BFF8A6BB912582E0530100007F8BE4/backupset/2021_01_31/o1_mf_nnndf_TAG20210131T094819_j1fjsn5j_.bkp
channel ORA_DISK_1: piece handle=/u01/app/oracle/fast_recovery_area/orcl12c/ORCL12C/49BFF8A6BB912582E0530100007F8BE4/backupset/2021_01_31/o1_mf_nnndf_TAG20210131T09 4819_j1fjsn5j_.bkp tag=TAG20210131T094819
channel ORA_DISK_1: restored backup piece 1
channel ORA_DISK_1: validation complete, elapsed time: 00:00:01
Finished validate at 06-FEB-21
============================================================================================
Détecter une corruption physique
============================================================================================
On crée maintenant une corruption physique en vérolant un bloc de données du tbs. Cela se fait en insérant des données incohérentes dans un bloc Oracle de 8K (le bloc N° 121) via la commande dd de Linux. Nous avons vu ci-dessus qu'il y a 127 blocs dans le tbs CROSS (colonne "Blocks Processed").
SQL> alter tablespace CROSS offline;
[oracle@vbgeneric ~]$ dd if=/u01/app/oracle/oradata/orcl12c/orcl/cross.dbf bs=8192 count=120 > t1
[oracle@vbgeneric ~]$ dd if=/dev/zero bs=8291 count=1 > t2
[oracle@vbgeneric ~]$ dd if=/u01/app/oracle/oradata/orcl12c/orcl/cross.dbf bs=8192 skip=121 count=26 > t3
[oracle@vbgeneric ~]$ cp /u01/app/oracle/oradata/orcl12c/orcl/cross.dbf /u01/app/oracle/oradata/orcl12c/orcl/cross.dbf.old
[oracle@vbgeneric ~]$ cat t1 t2 t3 > /u01/app/oracle/oradata/orcl12c/orcl/cross.dbf
Aïe, impossible de mettre le tbs online...
SQL> alter tablespace CROSS online;
alter tablespace CROSS online
*
ERROR at line 1:
ORA-01157: cannot identify/lock data file 21 - see DBWR trace file
ORA-01110: data file 21: '/u01/app/oracle/oradata/orcl12c/orcl/cross.dbf'
Le VALIDATE échoue mais est-ce à cause du fait que le tbs est offline ou de l'erreur que j'ai provoquée?
L'erreur "RMAN-06169: could not read file header for datafile 21 error reason 4" est pour moi liée à l'état du tbs donc ce test n'est pas suffisant pour voir quels sont les messages générés par le VALIDATE.
RMAN> validate tablespace CROSS;
Starting validate at 06-FEB-21
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=269 device type=DISK
RMAN-06169: could not read file header for datafile 21 error reason 4
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure of validate command at 02/06/2021 08:00:57
RMAN-06056: could not access datafile 21
Je vais alors sous Linux recopier la sauvegarde du datafile pour écraser le corrompu et ainsi pouvoir remettre online le tbs; attention, on parle bien des fichiers de la base, pas des backups RMAN.
[oracle@vbgeneric ~]$ mv /u01/app/oracle/oradata/orcl12c/orcl/cross.dbf.old /u01/app/oracle/oradata/orcl12c/orcl/cross.dbf
[oracle@vbgeneric ~]$ sqlplus SYS@orcl as sysdba
SQL> alter tablespace CROSS online;
Tablespace altered.
Et maintenant que le tbs est online, je recopie le fichier corrompu comme fichier du tbs SANS mettre celui-ci offline.
[oracle@vbgeneric ~]$ cp /u01/app/oracle/oradata/orcl12c/orcl/cross.dbf.CORRUPT /u01/app/oracle/oradata/orcl12c/orcl/cross.dbf
Dans ce tbs je peux créer une table, des enregistrements certainement parce que les blocs corrompus ne sont pas utilisés par Oracle lors de ces opérations.
SQL> create table zzvalidate (id number) tablespace cross;
SQL> insert into zzvalidate values (1);
SQL> insert into zzvalidate select * from zzvalidate;
...
SQL> /
256 rows created.
SQL> commit;
Et si je relance VALIDATE, on voit des messages d'erreur différents du précédent lorsque le tbs était offline, preuve que la corruption de blocs a bien été détectée : "RMAN-03009: failure of validate command", "ORA-01122: database file 21 failed verification check" et "ORA-27046: file size is not a multiple of logical block size". Visiblement les données insérées via la commande dd ont créé un bloc de données de taille anormale.
RMAN> validate tablespace CROSS;
Starting validate at 06-FEB-21
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=269 device type=DISK
channel ORA_DISK_1: starting validation of datafile
channel ORA_DISK_1: specifying datafile(s) for validation
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03009: failure of validate command on ORA_DISK_1 channel at 02/06/2021 08:12:00
ORA-01122: database file 21 failed verification check
ORA-01110: data file 21: '/u01/app/oracle/oradata/orcl12c/orcl/cross.dbf'
ORA-01565: error in identifying file '/u01/app/oracle/oradata/orcl12c/orcl/cross.dbf'
ORA-27046: file size is not a multiple of logical block size
Additional information: 1
Tiens, il n'y a rien dans V$DATABASE_BLOCK_CORRUPTION... bizarre! bon, pas grave, l'objectif était de voir la sortie de la commande VALIDATE en cas de bloc corrompus.
SQL> connect SYS@orcl as sysdba
SQL> select * from v$database_block_corruption;
no rows selected
DBVERIFY
Je lance l'utilitaire Oracle DBVERIFY (commande dbv) pour faire une double vérification. Zut, l'erreur n'est pas parlante.
[oracle@vbgeneric ~]$ dbv FILE=/u01/app/oracle/oradata/orcl12c/orcl/cross.dbf FEEDBACK=100
DBVERIFY: Release 12.2.0.1.0 - Production on Sun Feb 7 06:56:06 2021
Copyright (c) 1982, 2017, Oracle and/or its affiliates. All rights reserved.
DBV-00102: File I/O error on FILE (/u01/app/oracle/oradata/orcl12c/orcl/cross.dbf) during end read operation (-1)
Et si je lance DBVERIFY sur un tbs non corrompu? Ah, c'est mieux, là encore la sortie est intéressante, surtout la ligne "Total Pages Marked Corrupt".
[oracle@vbgeneric ~]$ dbv FILE=/u01/app/oracle/oradata/orcl12c/orcl/users01.dbf FEEDBACK=100
DBVERIFY - Verification starting : FILE = /u01/app/oracle/oradata/orcl12c/orcl/users01.dbf
................................................................................
.................
DBVERIFY - Verification complete
Total Pages Examined : 9760
Total Pages Processed (Data) : 6795
Total Pages Failing (Data) : 0
Total Pages Processed (Index): 324
Total Pages Failing (Index): 0
Total Pages Processed (Lob) : 401
Total Pages Failing (Lob) : 0
Total Pages Processed (Other): 920
Total Pages Processed (Seg) : 0
Total Pages Failing (Seg) : 0
Total Pages Empty : 1320
Total Pages Marked Corrupt : 0
Total Pages Influx : 0
Total Pages Encrypted : 0
Highest block SCN : 2093534 (0.2093534)
Bon, j'ai l'impression que la corruption faite dans mon tbs pose pb à Oracle pour être détectée :-(