Récupération d’informations

La log RMAN n’est pas très encourageante :

RMAN-03002: failure of backup plus archivelog command at 08/15/2014 00:31:16
RMAN-03009: failure of backup command on ORA_DISK_2 channel at 08/15/2014 00:25:26
ORA-19566: exceeded limit of 0 corrupt blocks for file /oracle/INSTANCEA/oradata1/tbsdata/blobs01.dbf

On est bien sur le backup d’un datafile et RMAN détecte une corruption. Puisque par défaut, il n’accepte aucune corruption, il s’arrête

Allons vérifier quel est l’objet impacté par la corruption via :
SELECT * FROM V$DATABASE_BLOCK_CORRUPTION;
Chose étonnante : dans mon cas, cette vue ne retourne aucune information. Elle est normalement remplie par RMAN (entre autres) lorsqu’il détecte la corruption et n’est purgée qu’une fois la corruption corrigée.

Toujours dans l’urgence, je ne cherche pas à comprendre pourquoi RMAN a levé une erreur mais je lance une nouvelle vérification des corruption via dbv (un binaire bien ancien !) :
dbv file=/oracle/INSTANCEA/oradata1/tbsdata/blobs01.dbf FEEDBACK=1000 blocksize=16384

DBVERIFY - Verification starting : FILE = /oracle/INSTANCEA/oradata1/tbsdata/blobs01.dbf
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
............................................

DBVERIFY - Verification complete

Total Pages Examined : 524288
Total Pages Processed (Data) : 0
Total Pages Failing (Data) : 0
Total Pages Processed (Index): 1036
Total Pages Failing (Index): 0
Total Pages Processed (Other): 517884
Total Pages Processed (Seg) : 0
Total Pages Failing (Seg) : 0
Total Pages Empty : 5368
Total Pages Marked Corrupt : 0
Total Pages Influx : 0
Total Pages Encrypted : 0
Highest block SCN : 2039179629 (0.2039179629)


J’ai exécuté la commande dbv avec en paramètre : FEEDBACK pour avoir un affichage de la progression, et BLOCKSIZE qui précise la taille du block Oracle. Si vous ne précisez pas BLOCKSIZE et que le datafile n’a pas une taille de 8KB, dbv va vous dire la taille du block qu’il pense être correcte.

Dans le résultat du dbv, aucune corruption n’est détectée ! Cette fois, c’est évident, il y a eu autre chose lors du backup mais pas de corruption du fichier sur disque.
Ouf, pas de perte de données.

Investigations dans l’alert.log

L’alert.log enregistre toutes les corruptions puisque c’est un point très sensible pour un SGBD.
Voici le contenu de mon fichier sur le créneau du backup :

Fri Aug 15 00:20:36 2014
ALTER SYSTEM ARCHIVE LOG
Fri Aug 15 00:20:36 2014
Thread 1 advanced to log sequence 27747 (LGWR switch)
Current log# 13 seq# 27747 mem# 0: /oracle/INSTANCEA/oraredo3/redo_g13m1.dbf
Current log# 13 seq# 27747 mem# 1: /oracle/INSTANCEA/oraredo1/redo_g13m2.dbf
Archived Log entry 25210 added for thread 1 sequence 27746 ID 0x9202e129 dest 1:
Fri Aug 15 00:25:04 2014
Hex dump of (file 8, block 470572) in trace file /oracle/diag/rdbms/instancea/INSTANCEA/trace/INSTANCEA_ora_5415.trc
Corrupt block relative dba: 0x02072e2c (file 8, block 470572)
Fractured block found during backing up datafile
Data in bad block:
type: 40 format: 2 rdba: 0x02072e2c
last change scn: 0x0000.7948a269 seq: 0x2 flg: 0x04
spare1: 0x0 spare2: 0x0 spare3: 0x0
consistency value in tail: 0x89032802
check value in block header: 0x576e
computed block checksum: 0xdf9e
Reread of blocknum=470572, file=/oracle/INSTANCEA/oradata1/tbsdata/blobs01.dbf. found same corrupt data
Reread of blocknum=470572, file=/oracle/INSTANCEA/oradata1/tbsdata/blobs01.dbf. found same corrupt data
Reread of blocknum=470572, file=/oracle/INSTANCEA/oradata1/tbsdata/blobs01.dbf. found same corrupt data
Reread of blocknum=470572, file=/oracle/INSTANCEA/oradata1/tbsdata/blobs01.dbf. found same corrupt data
Reread of blocknum=470572, file=/oracle/INSTANCEA/oradata1/tbsdata/blobs01.dbf. found same corrupt data
Fri Aug 15 00:25:16 2014
Checker run found 1 new persistent data failures
Fri Aug 15 00:37:45 2014
Thread 1 advanced to log sequence 27748 (LGWR switch)
Current log# 11 seq# 27748 mem# 0: /oracle/INSTANCEA/oraredo1/redo_g11m1.dbf
Current log# 11 seq# 27748 mem# 1: /oracle/INSTANCEA/oraredo2/redo_g11m2.dbf
Fri Aug 15 00:37:46 2014
Archived Log entry 25211 added for thread 1 sequence 27747 ID 0x9202e129 dest 1:



L’alert.log reconnait qu’il y a bien eu une corruption détectée par RMAN et il nous en dit plus. La corruption est de type : « Fractured block ».

Qu’est-ce que les corruptions fractured block ?

Cette corruption se produit généralement lors des backups/restores RMAN. Voici ce qui se passe :

  • RMAN demande à l’OS le block Oracle ID : 470572
  • Ce block a une taille de 16KB niveau Oracle ; niveau OS, le fichier est sur un FS dont la taille des blocks est de 4KB, l’OS va donc renvoyer 4 blocks de 4KB.
  • Lorsque RMAN a reçu les 4x4KB, il calcule un checksum et le compare au checksum écrit dans le header du block Oracle.

Dans mon cas, les 2 checksums n’étaient pas identiques ; le block Oracle est étiqueté corrompu par RMAN

Lorsque l’OS a retourné les 4x4KB, il y a eu une écriture sur ce block en parallèle.
Exemple : l’OS a envoyé 4KB avant la modification et 12KB après la modification. Du coup, le checksum contenu dans le header correspond au block AVANT écriture alors que les 12KB suivants ont déjà été modifiés.

RMAN est programmé pour prendre en charge un tel comportement et il va tenter de refaire la lecture du block. C’est ce qu’on voit dans l’alert.log (Reread of ….).
Dans mon cas, les 5 relectures ont données le même résultat : le block Oracle n’a pas pu être lu dans un état consistant.

Mon file system a-t-il une taille de block différente des blocks Oracle ?

Voici la commande pour trouver la taille du block FS (donc niveau OS) en étant root :
A vous de renseigner le bon device ;)

root@sv00214:/root# tune2fs -l /dev/mapper/vge2-lv201 | grep -i block
Block count: 22544384
Reserved block count: 1127136
Free blocks: 2937700
First block: 0
Block size: 4096
Reserved GDT blocks: 1018
Blocks per group: 32768
Inode blocks per group: 512
Flex block group size: 16
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
Journal backup: inode blocks

J’ai bien un FS avec des blocks de 4KB.
Fractured_block.png

Conclusion

Les corruptions « Fractured Blocks » sont un type de corruption très particuliers. Dans mon cas, cette corruption était un faux-positif mais Oracle/RMAN ne peut pas détecter si cette « fracturation » est temporaire donc l’erreur est remontée comme un block corrompu.
Ces cas ne se présentent que rarement : il faut pour commencer des tailles de blocks qui ne sont pas identiques (c’est généralement le cas aujourd'hui) mais surtout, il faut une activité importante lors du backup : il faut qu’il y ait une modification lors de la lecture. De plus, il faut une charge très soutenue puisque RMAN tente 5 lectures du block avant de le marquer comme « fracturé ».