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

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 ?

13 réflexions sur “Oracle 11g Release 2 Data Guard (3/5) : Automatic Block Media Recovery”

  1. Ping : Active Data Guard 11g Release 2 (5/5) : BCTF et RECOVER NOREDO sur la Standby | EASYTEAM

  2. Ping : Active Data Guard 11g Release 2 (5/5) : BCTF et RECOVER NOREDO sur la Standby | EASYTEAM LE BLOG

  3. Ping : Oracle Database 11g Release 2 Data Guard (7/5): Observer et Fast Start Failover « EASYTEAM LE BLOG

  4. Ping : Oracle Database 11g Release 2 Data Guard (6/5): Créer une standby logique avec le broker « EASYTEAM LE BLOG

  5. 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.

    1. 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

  6. 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.

    1. 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.

  7. 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

    1. 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 ?

      1. 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.

  8. 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 ?

Les commentaires sont fermés.