![]() |
|||||||||||||||||||||||||||||||||||||||||||||
|
La corruption de blocs [26/11/2003]
Qui n’a pas rencontré, au moins une fois, des blocs corrompus, qui ne s’est pas posé la question depuis quand existent-ils dans la base ? Plusieurs causes peuvent déterminer la corruption des blocs : interface d’entrée/sortie endommagée ou boguée (par exemple contrôleur disque défectueux), entrées/sorties OS incomplètes à cause d’un problème de cache, logiciels de réparation de disque (qui survient au boot suivant après l’écran bleu ?), mémoire défectueuse, etc.
Un bloc est écrit de manière binaire. ORACLE estime qu’un bloc est corrompu quand il n’est plus conforme à ce format. La vérification de cette conformité, présentée dans la première partie du livre, se fait d’habitude dans les couches supérieures du cache. Rappelons-nous qu’un bloc dans le cache contient des informations sur la version du bloc, les transactions le concernant et une information de checksum (non utilisée en standard afin de ne pas alourdir le traitement). Si une incohérence du bloc est détectée, en fonction de sa gravité et de la couche du noyau où elle a été découverte, le bloc est dit ‘media corrupt’ ou ‘software corrupt’.
Généralement, les erreurs ORA-1578 ou ORA-600 [3374] signalent la présence d’un ou plusieurs blocs corrompus. Nous pouvons dépister ces blocs en appliquant diverses méthodes, plus ou moins astucieuses :
Analyze table table_name validate structure cascade
Cette commande vérifie chaque bloc au niveau du cache et plus haut. Les index sont également analysés grâce à cet ordre.
Utiliser DB_VERIFY
DB_VERIFY est un utilitaire qui contrôle la cohérence physique des fichiers ORACLE. Les blocs de la base sont montés dans la SGA et les vérifications se font au niveau du cache. Il est utile, également, pour vérifier que les fichiers sauvegardés pourront être utilisés lors d’une restauration. Il accepte quelques paramètres dont un, non négligeable, est la taille du bloc. Il porte différents noms en fonction de la plate-forme OS. Vous pouvez vérifier les fichiers des données ou les fichiers redo log archivés.
Veillez à appliquer DB_VERIFY avec l’instance arrêtée, sinon … Ses paramètres possibles sont affichés avec la commande :
Db_verify help=yes Bien que vous n’êtes pas tenus de donner la plage de blocs à vérifier pour des fichiers OS (elle est obligatoire pour les raw devices), une bonne habitude est de l’indiquer systématiquement à DB_VERIFY !
Select bytes from v$datafile where name = 'fichier'; Select value from v$parameter where name = 'db_block_size'; Dbverf file=fichier, end=…
Checksum des blocsORACLE prévoit, par son architecture, la possibilité de marquer pour chaque bloc son checksum dans le bloc lui-même. L’écriture et l’analyse du checksum alourdissent d'environ 10% à 20% la charge globale d’ORACLE, mais l'analyse garantit l'alerte immédiate lors d’une non concordance. Les checksums sont calculés par DBWR et DIRECT LOADER lors de l’écriture du bloc et sont lus par les process serveurs. Le calcul et la vérification du checksum sont provoqués par les paramètres LOG_BLOCK_CHECKSUM pour les fichiers redo log et DB_BLOCK_CHECKSUM pour les fichiers de données.
Le paramètre _DB_BLOCK_CACHE_PROTECT (mis à TRUE), dans init.ora, renforce la protection du cache layer. Si jamais un bloc est corrompu dans le cache, il ne sera pas écrit sur le disque (globalement vous aurez un ORA-600 minimum ;-))
Dans la même plage de vérifications, nous disposons de plusieurs events pour vérifier la corruption des blocs. Ces events provoquent une corruption des blocs lors de la détection des erreurs :
alter session set events '102xx trace name context forever, level 10'; L' event 10210 vérifie les blocs de données
L'event 10211 verifie les blocs d’index.
L'event 10212 vérifie les blocs de cluster.
L'event 10225 vérifie les informations en fet$/uset$ pour toute corruption.
La réparation des blocs corrompusEn réalité, la réparation n’en est pas une : il s’agit plutôt d’une restauration ou d’un ensemble d’actions qui passe, presque systématiquement, par la destruction des objets (contenant les blocs corrompus leur recréation et leur repopulation.
Avant de procéder à une quelconque restauration , si vous en avez la possibilité, vous devriez analyser l’ampleur des dégâts en puisant toutes les informations des fichiers traces (ORACLE et OS). Une fois, les problèmes OS résolus, vous pouvez vous attaquer à la restauration. Votre objectif est presque atteint si vous arrivez à déterminer le numéro du fichier qui contient le bloc corrompu (i) et l’identifiant de ce bloc (j).
Déterminer l’objet qui contient le bloc endommagé :
SELECT owner, segment_name, segment_type
FROM dba_extents
WHERE file_id = i
AND j BETWEEN block_id AND block_id + blocks - 1;
Si le segment en cause est un index, trouver la table qu’il indexe :
SELECT table_owner, table_name
FROM dba_indexes
WHERE index_name = 'segment_name';
Si le segment en cause est un cluster, trouver la table (ou les tables) concernée :
SELECT owner, table_name FROM dba_tables WHERE cluster_name = 'segment_name'; Si le segment est une table, noter son nom et son proprietaire.
Passez l’ANALYZE plusieurs fois pour vérifier que vous n’êtes pas devant un faux problème.
Pour un index ou une table :
ANALYZE TABLE owner.tablename VALIDATE STRUCTURE CASCADE; Pour un cluster :
ANALYZE CLUSTER owner.clustername VALIDATE STRUCTURE CASCADE; Si les problèmes sont dus à un contrôleur défectueux ou à un disque, déplacer le fichier en cause sur un autre support.
Restauration en mode ARCHIVELOG
Mettre le fichier offline, le restaurer (sur un disque correct), le renommer, le recouvrir, le mettre online.
Restauration en mode NOARCHIVELOG
Restaurer le fichier (sur un disque correct), le renommer, le recouvrir, le mettre online (Si vous avez la chance que les redo logs online suffisent !!!!!!!!!!!!!!!!!!!!!!!!!!!!)
Vous ne pouvez pas mettre un fichier offline en mode noarchivelog ! Quand la restauration est achevée, réanalyser l’objet initialement endommagé. Rien ne prouve que le bloc était corrompu hier, avant-hier, etc, mais il n’avait pas été utilisé après sa corruption. Ces étapes devraient être exécutées pour tous les fichiers qui contiennent des blocs abimés.
Si le problème persiste, préparons nous pour la mauvaise nouvelle : au mieux, nous pouvons espérer récupérer les données qui ne sont pas contenues dans les blocs corrompus ! Dans cette étape, pensons à l’économie de temps et d’énergie réalisée si nous supprimons un index et nous le recréons. Si nous avons un export de confiance, utilisons-le. Si nous nous approchons de la réalité ? en (re)passant deux ou trois batch, faisons-le !
Pour récupérer les données, si l’on connaît les blocs corrompus, nous pouvons extraire les données en évitant les identifiants de lignes (rowids) des blocs corrompus :
CREATE TABLE recup AS SELECT * FROM table_corrompue WHERE 1 = 2; INSERT INTO recup SELECT /*+ ROWID(table_corrompue) */ * FROM table_corrompue WHERE rowid <= 'low_rowid_of_corrupt_block'; INSERT INTO recup SELECT /*+ ROWID(table_corrompue) */ * FROM table_corrompue WHERE rowid >= 'high_rowid_of_corrupt_block'; Inutile de vous dire que les cas de corruption d’un seul bloc sont rares, vous aurez à gérer la liste complète et implicitement une liste complexe d’inégalités.
L'event 10231L’utilisation de l’event 10231 permet de sélectionner les données autour des blocs corrompus. (ORACLE occulte les blocs corrompus lors d’un full table scan pendant l’utilisation de cet event).
event="10231 trace name context forever, level 10" L’event 10233 est similaire à l’event 10231, mais il fonctionne avec les index (en range scan). Malheureusement, les données des blocs corrompus seront perdues !
Voir aussi Metalink 28814.1
|
||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||