Sauter au contenu

Oracle 11g Release 2 Data Guard (3/5) : Automatic Block Media Recovery

5 octobre 2009
tags:
by

Le “Block Media Recovery” ou BMR est la possibilité de restaurer un bloc Oracle en cas de corruption. Jusqu’à Oracle 11g Database Release 1, seul Oracle Oracle Recovery Manager, RMAN, permet de restaurer simplement un bloc. Avec la version 11.2 de la base de données, lorsque vous utilisez Active Data Guard et que vous utilisez une standby database et Real Time Query, les corruptions de données sont corrigées automatiquement. Cette nouvelle fonctionnalité permet d’éviter les erreurs ORA-01578 de manière automatique et quasiment transparente. Cette article illustre cette fonctionnalité à travers une méthode simple pour corrompre, tour à tour, la base de données primaire et la standby.

Cet article est le troisième d’une série plus large que je vous invite à découvrir ci-dessous :

Il s’agit d’un tour d’horizon assez complet de l’état de l’art de Data Guard en 11g Release 2. Bien sur, si vous avez d’autres idées, n’hésitez pas à les partager en laissant vos commentaires…

Préambule

Pour commencer, il faut configurer une standby physique en “real time query”. Pour cela, je vous renvoie au premier article et au second article de la série. Dans la configuration qui suit, BLACK est la base de données primaire et WHITE, la base de données standby en real time apply. J’ai effectué mes tests sur Linux x86.

dgmgrl sys/change_on_install@black

show database white;

Database - white
  Role:            PHYSICAL STANDBY
  Intended State:  APPLY-ON
  Transport Lag:   0 seconds
  Apply Lag:       0 seconds
  Real Time Query: ON
  Instance(s):
    WHITE

Database Status:
SUCCESS

exit

Corruption d’un bloc sans une Standby “Real Time Query”

Pour commencer, vous pouvez désactiver la base de données standby “Real Time Query” pour visualiser ce qu’il se passe lorsque un bloc est corrompu sans Active Data Guard. Pour cela, connectez-vous à la standby avec le client du broker et démarrer la base standby en mode mount :

dgmgrl sys/change_on_install@white

shutdown abort
ORACLE instance shut down.
startup mount;
ORACLE instance started.
Database mounted.
show database white;

Database - white

Role:            PHYSICAL STANDBY
Intended State:  APPLY-ON
Transport Lag:   0 seconds
Apply Lag:       0 seconds
Real Time Query: OFF
Instance(s):
WHITE

Database Status:
SUCCESS

exit;

Pour la suite, nous allons répérer un bloc à corrompre. Pour cet exemple, nous allons utiliser la table exemple SCOTT.EMP. Le package DBMS_ROWID permet de repérer le bloc d’une ligne à partir de son rowid :

sqlplus sys/change_on_install@black as sysdba

set serveroutput on

declare
   v_rowid_type number;
   v_object_number number;
   v_relative_fno number;
   v_block_number number;
   v_row_number number;
begin
   for i in (select rowid, ename
            from scott.emp) loop
      dbms_rowid.ROWID_INFO(
            i.rowid,
            v_rowid_type,
            v_object_number,
            v_relative_fno,
            v_block_number,
            v_row_number);
      dbms_output.put_line(
            'Employee: '||i.ename||
            ' - block: '||to_char(v_block_number ));
   end loop;
end;
/

Employee: SMITH - block: 151
Employee: ALLEN - block: 151
Employee: WARD - block: 151
Employee: JONES - block: 151
Employee: MARTIN - block: 151
Employee: BLAKE - block: 151
Employee: CLARK - block: 151
Employee: SCOTT - block: 151
Employee: KING - block: 151
Employee: TURNER - block: 151
Employee: ADAMS - block: 151
Employee: JAMES - block: 151
Employee: FORD - block: 151
Employee: MILLER - block: 151

Nous allons donc corrompre le bloc 151 de notre datafile. Pour cela, nous allons utiliser la commande dd qui est facile à utiliser lorsque vous n’utilisez pas Automatic Storage Manager (Avec ASM, il faut d’abord repérer la position des extents du datafiles dans le diskgroup). Après que vous ayez corrompu le bloc, Oracle vous retourne l’erreur ORA-01578 lorsque vous tentez d’y accéder :

select file_name
   from dba_data_files
 where tablespace_name='USERS';

FILE_NAME
-----------------------------------------
/u01/app/oracle/oradata/BLACK/users01.dbf

! ls -l /u01/app/oracle/oradata/BLACK/users01.dbf

! dd if=/dev/zero -
   of=/u01/app/oracle/oradata/BLACK/users01.dbf -
   bs=8k count=1 seek=151 conv=notrunc

alter system flush buffer_cache;

select * from scott.emp;
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 4, block # 151)
ORA-01110: data file 4: '/u01/app/oracle/oradata/BLACK/users01.dbf'

exit;

Note
le paramètre conv=notrunc de la commande dd permet de ne pas tronquer le fichier après le bloc que vous modifiez, ce qui est le comportement par défaut.

Corriger un bloc corrompu avec la base de données Standby “Real Time Query”

Pour corriger le bloc corrompu, vous pouvez bien entendu utiliser Recovery Manager; Au lieu de celà, nous allons simplement activer la standby en mode “Real Time Query” :

dgmgrl sys/manager@white

show database white;

Database - white

  Role:            PHYSICAL STANDBY
  Intended State:  APPLY-ON
  Transport Lag:   0 seconds
  Apply Lag:       0 seconds
  Real Time Query: OFF
  Instance(s):
    WHITE

Database Status:
SUCCESS

shutdown immediate;
ORA-01109: database not open
Database dismounted.
ORACLE instance shut down.

startup
ORACLE instance started.
Database mounted.
Database opened.

show database white;

Database - white

  Role:            PHYSICAL STANDBY
  Intended State:  APPLY-ON
  Transport Lag:   0 seconds
  Apply Lag:       0 seconds
  Real Time Query: ON
  Instance(s):
    WHITE

Database Status:
SUCCESS

exit;

Maintenant, il suffit d’accéder au bloc corrompu sur la base de données primaire pour corriger l’erreur :

sqlplus sys/change_on_install@black as sysdba

set pages 1000

select empno, ename
  from scott.emp;

EMPNO ENAME
----- -------
 7369 SMITH
 7499 ALLEN
 7521 WARD
 7566 JONES
 7654 MARTIN
 7698 BLAKE
 7782 CLARK
 7788 SCOTT
 7839 KING
 7844 TURNER
 7876 ADAMS
 7900 JAMES
 7902 FORD
 7934 MILLER

L’erreur est corrigée, comme par magie. Pour comprendre ce qui s’est passé, allez voir le fichier alert.log et vous y découvrirez un message indiquant que la correction automatique du bloc a été déclenchée. Voici le-dit extrait sur ma base de données :

Sun Oct 04 13:27:13 2009
Hex dump of (file 4, block 151) in trace file /u01/app/oracle/diag/rdbms/black/BLACK/trace/BLACK_ora_15682.trc
Corrupt block relative dba: 0x01000097 (file 4, block 151)
Completely zero block found during buffer read
Reading datafile '/u01/app/oracle/oradata/BLACK/users01.dbf' for corruption at rdba: 0x01000097 (file 4, block 151)
Reread (file 4, block 151) found same corrupt data
Starting background process ABMR
Sun Oct 04 13:27:13 2009
ABMR started with pid=37, OS id=15692
Auto BMR service is active.
Requesting Auto BMR for (file# 4, block# 151)
Waiting Auto BMR response for (file# 4, block# 151)
Auto BMR successful

Quel est l’impact de la correction automatique de la corruption ?

Re-faîtes le même test, cette fois-ci en ayant déjà la base de données en mode “Real Time Query”

  • Sans corruption de données
sqlplus / as sysdba

alter system flush buffer_cache;

set timing on
select empno, ename
  from scott.emp;
[...]
Elapsed: 00:00:00.01
  • Avec corruption de données
sqlplus / as sysdba

! dd if=/dev/zero -
   of=/u01/app/oracle/oradata/BLACK/users01.dbf -
   bs=8k count=1 seek=151 conv=notrunc

alter system flush buffer_cache;

set timing on
select empno, ename
  from scott.emp;
[...]
Elapsed: 00:00:00.48

Vous pouvez encore vérifier dans le fichier alert.log que la gestion automatique du “Block Media Recovery” a été déclenchée. Vous constaterez que si l’impact n’est pas transparent, il est relativement négligeable; bien sur, ce temps dépend du lag de la standby.

Corruption de la base de données Standby

La gestion automatique de la corruption de bloc est également disponible sur la standby. Pour vous en persuader, vous pouvez effectuer le même test depuis la base standby en mode “Real Time Query”. Remarquez que dans ce cas, voulu(*) ou pas une erreur est renvoyée à l’utilisateur :

sqlplus sys/change_on_install@white as sysdba

alter system flush buffer_cache;

! dd if=/dev/zero -
   of=/u01/app/oracle/oradata/WHITE/users01.dbf -
   bs=8k count=1 seek=151 conv=notrunc

select empno, ename
from scott.emp;
*
ERROR at line 2:
ORA-01578: ORACLE data block corrupted (file # 4, block # 151)
ORA-01110: data file 4: '/u01/app/oracle/oradata/WHITE/users01.dbf'

Si vous ré-exécutez la requête, le bloc est corrigé :

select empno, ename
   from scott.emp;

EMPNO ENAME
----- --------
 7369 SMITH
 7499 ALLEN
 7521 WARD
 7566 JONES
 7654 MARTIN
 7698 BLAKE
 7782 CLARK
 7788 SCOTT
 7839 KING
 7844 TURNER
 7876 ADAMS
 7900 JAMES
 7902 FORD
 7934 MILLER

Le fichier alert.log montre que la corruption est détectée :

Hex dump of (file 4, block 151) in trace file /u01/app/oracle/diag/rdbms/white/WHITE/trace/WHITE_ora_17556.trc
Corrupt block relative dba: 0x01000097 (file 4, block 151)
Completely zero block found during multiblock buffer read
Reading datafile '/u01/app/oracle/oradata/WHITE/users01.dbf' for corruption at rdba: 0x01000097 (file 4, block 151)
Reread (file 4, block 151) found same corrupt data
Errors in file /u01/app/oracle/diag/rdbms/white/WHITE/trace/WHITE_ora_17556.trc  (incident=97362):
ORA-01578: ORACLE data block corrupted (file # 4, block # 151)
ORA-01110: data file 4: '/u01/app/oracle/oradata/WHITE/users01.dbf'
Incident details in: /u01/app/oracle/diag/rdbms/white/WHITE/incident/incdir_97362/WHITE_ora_17556_i97362.trc
Sun Oct 04 14:03:07 2009
Sweep [inc][97362]: completed
Sun Oct 04 14:03:08 2009
Trace dumping is performing id=[cdmp_20091004140308]
Sun Oct 04 14:03:09 2009
Sweep [inc2][97362]: completed

Conclusion

Ces changements, à priori mineurs, à la lumière de ces tests, non seulement fonctionnent mais apportent un vrai plus à l’infrastructure Active Data Guard. Et ce n’est qu’un début puisque dans le prochain article, nous testerons la possibilité offerte par la standby “Real Time Query” de garantir la fraicheur des données interrogée sur la base secondaire. J’espère pouvoir vous faire partager notre enthousiasme pour ces nouvelles fonctionnalités. Qu’en pensez-vous ?

(*) La base de données standby a un SCN plus petit, même très proche, que le SCN de la base de données primaire; il est possible que la requête doivent être arrêtée parce que la standby ne peut pas garantir que le bloc remonté ne contient pas des données modifiées depuis. Ceci dépend de la manière dont le bloc est accédé et il se peut que ce soit une limite de l’implémentation actuelle (malgré la présence des UNDO). Il faudrait activer les traces sur la primaire et démonter le mécanisme pour en savoir plus. Y a-t-il un curieux/courageux pour comprendre ce qu’il se passe plus en détail ?

11 Commentaires laisser un →
  1. 8 octobre 2009 11:29

    Génial cet article !

    la détection du bloc corrompu par le noyau se fait comment ? c’est au moment ou tu le lis qu’il le détecte ? Que se passe-t-il si personne ne lit ce bloc, dans ce cas ?

  2. arkzoyd permalien
    8 octobre 2009 11:46

    Chaque bloc en plus d’avoir une structure définie contient des checksums. C’est d’ailleurs comme ça que la corruption est détectée. C’est aussi pour ça que créer un datafile prend du temps; et que Exadata va beaucoup plus vite pour créer des grosses bases de données, même vide comparé à une base Oracle sans Exadata Cell Storage Server;

    La corruption est détectée lorsque le bloc est monté en mémoire, en effet.

    Ta question est très intéressante, parce qu’elle en amène un autre à laquelle je ne sais pas répondre:

    Réponse 1 (simple) : Si le bloc n’est jamais accédé, il n’est jamais corrigé mais cela n’a pas d’impact puisqu’il n’est jamais accédé : Quoique en janvier l’année prochaine ou lors d’un archivage dans 3 ans !

    Réponse 2 (plus compliquée) : Tu accèdes aux blocs pour faire tes sauvegardes, ou les valider; c’est d’ailleurs une des raisons pour lesquelles il vaut mieux utiliser RMAN ou valider les blocs régulièrement. Mais dans ce cas, je ne sais pas si les corruptions sont corrigées

    • 8 octobre 2009 16:37

      C’était un peu le sens de ma question, car dans ton test tu accèdes au bloc juste après l’avoir pourri, mais imagine que c’est 6 mois après ?

      • arkzoyd permalien
        8 octobre 2009 16:46

        En faisant des sauvegardes avec RMAN, ou en validant les datafiles de manière régulière, on peut éviter de découvrir une corruption 6 mois après. Cela dit, la question reste ouverte, à savoir si Active Data Guard résoud, dans ce cas également le problème de corruption. Je testerai.

  3. arkzoyd permalien
    8 octobre 2009 23:20

    Pour continuer la discussion précédente, j’ai fait le test avec RMAN. Dans ce cas :
    1) le bloc corrompu est détecté
    2) Il n’est pas automatiquement corrigé.
    3) Advise Failure indique de passer la commande “recover datafile 4 block 151;”
    4) La dite commande utilise la standby (je n’ai pas de backup ni de datafilecopy pour aller au bout
    5) après ça, le backup passe

    Après avoir corrumpu le bloc, voici la sortie de mes commandes RMAN:

    oracle@arkzoyd-easyteam:~$ rman target sys/manager@black
    
    Recovery Manager: Release 11.2.0.1.0 - Production on Thu Oct 8 23:08:35 2009
    
    Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.
    
    connected to target database: BLACK (DBID=383458568)
    
    RMAN> backup database;
    
    Starting backup at 08-OCT-09
    using target database control file instead of recovery catalog
    allocated channel: ORA_DISK_1
    channel ORA_DISK_1: SID=29 device type=DISK
    channel ORA_DISK_1: starting compressed full datafile backup set
    channel ORA_DISK_1: specifying datafile(s) in backup set
    input datafile file number=00001 name=/u01/app/oracle/oradata/BLACK/system01.dbf
    input datafile file number=00002 name=/u01/app/oracle/oradata/BLACK/sysaux01.dbf
    input datafile file number=00004 name=/u01/app/oracle/oradata/BLACK/users01.dbf
    input datafile file number=00005 name=/u01/app/oracle/oradata/BLACK/example01.dbf
    input datafile file number=00003 name=/u01/app/oracle/oradata/BLACK/undotbs01.dbf
    input datafile file number=00006 name=/u01/app/oracle/oradata/BLACK/streams_tbs01.dbf
    channel ORA_DISK_1: starting piece 1 at 08-OCT-09
    RMAN-03009: failure of backup command on ORA_DISK_1 channel at 10/08/2009 23:08:43
    ORA-19566: exceeded limit of 0 corrupt blocks for file /u01/app/oracle/oradata/BLACK/users01.dbf
    continuing other job steps, job failed will not be re-run
    channel ORA_DISK_1: starting compressed full datafile backup set
    channel ORA_DISK_1: specifying datafile(s) in backup set
    including current control file in backup set
    including current SPFILE in backup set
    channel ORA_DISK_1: starting piece 1 at 08-OCT-09
    channel ORA_DISK_1: finished piece 1 at 08-OCT-09
    piece handle=/u01/app/oracle/backup/BLACK/0mkram3r_1_1 tag=TAG20091008T230841 comment=NONE
    channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
    RMAN-00571: ===========================================================
    RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
    RMAN-00571: ===========================================================
    
    RMAN-03009: failure of backup command on ORA_DISK_1 channel at 10/08/2009 23:08:43
    ORA-19566: exceeded limit of 0 corrupt blocks for file /u01/app/oracle/oradata/BLACK/users01.dbf
    
    RMAN> list failure;
    
    List of Database Failures
    =========================
    
    Failure ID Priority Status    Time Detected Summary
    ---------- -------- --------- ------------- -------
    1842       HIGH     OPEN      08-OCT-09     
    Datafile 4: '/u01/app/oracle/oradata/BLACK/users01.dbf' contains one or more corrupt blocks
    
    RMAN> advise failure;
    
    List of Database Failures
    =========================
    
    Failure ID Priority Status    Time Detected Summary
    ---------- -------- --------- ------------- -------
    1842       HIGH     OPEN      08-OCT-09     
    Datafile 4: '/u01/app/oracle/oradata/BLACK/users01.dbf' contains one or more corrupt blocks
    
    analyzing automatic repair options; this may take some time
    using channel ORA_DISK_1
    analyzing automatic repair options complete
    
    Mandatory Manual Actions
    ========================
    no manual actions available
    
    Optional Manual Actions
    =======================
    1. Shut down, mount the database and try flush redo using ALTER SYSTEM FLUSH REDO TO 'standby name' command.  
    Then perform a Data Guard role change (failover).  Available standbys: white.
    
    Automated Repair Options
    ========================
    Option Repair Description
    ------ ------------------
    1      Perform block media recovery of block 151 in file 4  
      Strategy: The repair includes complete media recovery with no data loss
      Repair script: /u01/app/oracle/diag/rdbms/black/BLACK/hm/reco_3761743400.hm
    
    RMAN> exit
    
    
    Recovery Manager complete.
    oracle@arkzoyd-easyteam:~$ cat  /u01/app/oracle/diag/rdbms/black/BLACK/hm/reco_3761743400.hm
       # block media recovery
       recover datafile 4 block 151;
    oracle@arkzoyd-easyteam:~$ rman target sys/manager@black
    
    Recovery Manager: Release 11.2.0.1.0 - Production on Thu Oct 8 23:11:49 2009
    
    Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.
    
    connected to target database: BLACK (DBID=383458568)
    
    RMAN>    recover datafile 4 block 151;
    
    Starting recover at 08-OCT-09
    using target database control file instead of recovery catalog
    allocated channel: ORA_DISK_1
    channel ORA_DISK_1: SID=25 device type=DISK
    finished standby search, restored 1 blocks
    
    starting media recovery
    media recovery complete, elapsed time: 00:00:01
    
    Finished recover at 08-OCT-09
    
    RMAN> list backup of datafile 4;
    
    specification does not match any backup in the repository
    
    RMAN> list datafilecopy all;
    
    specification does not match any datafile copy in the repository
    
    RMAN> backup database;
    
    Starting backup at 08-OCT-09
    using channel ORA_DISK_1
    channel ORA_DISK_1: starting compressed full datafile backup set
    channel ORA_DISK_1: specifying datafile(s) in backup set
    input datafile file number=00001 name=/u01/app/oracle/oradata/BLACK/system01.dbf
    input datafile file number=00002 name=/u01/app/oracle/oradata/BLACK/sysaux01.dbf
    input datafile file number=00004 name=/u01/app/oracle/oradata/BLACK/users01.dbf
    input datafile file number=00005 name=/u01/app/oracle/oradata/BLACK/example01.dbf
    input datafile file number=00003 name=/u01/app/oracle/oradata/BLACK/undotbs01.dbf
    input datafile file number=00006 name=/u01/app/oracle/oradata/BLACK/streams_tbs01.dbf
    channel ORA_DISK_1: starting piece 1 at 08-OCT-09
    channel ORA_DISK_1: finished piece 1 at 08-OCT-09
    piece handle=/u01/app/oracle/backup/BLACK/0pkramhk_1_1 tag=TAG20091008T231604 comment=NONE
    channel ORA_DISK_1: backup set complete, elapsed time: 00:00:55
    channel ORA_DISK_1: starting compressed full datafile backup set
    channel ORA_DISK_1: specifying datafile(s) in backup set
    including current control file in backup set
    including current SPFILE in backup set
    channel ORA_DISK_1: starting piece 1 at 08-OCT-09
    channel ORA_DISK_1: finished piece 1 at 08-OCT-09
    piece handle=/u01/app/oracle/backup/BLACK/0qkramjb_1_1 tag=TAG20091008T231604 comment=NONE
    channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
    Finished backup at 08-OCT-09

    J’ai mis en gras la ligne intéressante; C’est dommage, le fichier alert.log ne dit pas comment le BMR c’est fait:

    Thu Oct 08 23:11:54 2009
    alter database recover datafile list clear
    Completed: alter database recover datafile list clear
    Started Block Media Recovery
    Recovery of Online Redo Log: Thread 1 Group 2 Seq 68 Reading mem 0
      Mem# 0: /u01/app/oracle/oradata/BLACK/redo02.log
    Recovery of Online Redo Log: Thread 1 Group 3 Seq 69 Reading mem 0
      Mem# 0: /u01/app/oracle/oradata/BLACK/redo03.log
    Completed Block Media Recovery

    Comme on peut s’y attendre le résultat est le même pour la commande VALIDATE.

    • arkzoyd permalien
      8 octobre 2009 23:27

      Comme quoi, RMAN ça en jette!

    • arkzoyd permalien
      13 octobre 2009 00:24

      Pour que RMAN puisse tirer parti de la base de données standby, il faut que celle ci soit en mode Real Time Query; Si la base de données n’est qu’en recover, il faudra fair un BMR à partir d’une sauvegarde.

  4. Hervé permalien
    20 octobre 2009 16:44

    D’après ce qui est dit dans la documentation, meme sans accéder au bloc, la correction doit pouvoir se faire au moment de l’application des logs.

    • Arkzoyd permalien
      20 octobre 2009 18:40

      Effectivement; sur la standby. Je n’ai pas testé ce scénario mais si un bloc est corrompu puis modifié… La correction pourrait être automatique. Je vais vérifier

Rétroliens

  1. Oracle Database 11g Release 2 Data Guard (6/5): Créer une standby logique avec le broker « EASYTEAM LE BLOG
  2. Oracle Database 11g Release 2 Data Guard (7/5): Observer et Fast Start Failover « EASYTEAM LE BLOG

Répondre

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Twitter picture

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Connexion à %s

Suivre

Get every new post delivered to your Inbox.

Joignez-vous à 385 followers