11g : Enregistrer les appels PL/SQL dans les redologs

Il y a deux ou trois trucs que je n’arrive toujours pas à faire fonctionner avec 11g ; la faute à mon manque de concentration sans doute ! Ajouter les appels PL/SQL dans les redo logs en fait visiblement parti et cette fois, il va falloir m’aider…

Voilà l’histoire : 11g permet théoriquement d’ajouter en « SUPPLEMENTAL LOG » les appels aux procédures PL/SQL. Selon ce que j’en comprends, cette fonctionnalité pourrait permettre de copier la réplication procédurale via Streams et ainsi (enfin ?) d’abandonner Oracle « Advanced Replication Option » que j’ai payé au propre comme au figuré dans une autre vie.

Le paramétrage est théoriquement simple et s’exécute en quelques minutes ; le script ci dessous passe la base de données en mode archivelog et active cette fonctionnalité :

sqlplus / as sysdba

shutdown immediate

startup mount

alter system set
log_archive_dest_1=
'LOCATION=/u02/app/oracle/oradata/ORCL/archives';

show parameter log_archive_format

NAME TYPE VALUE
------------------ ------ ------------
log_archive_format string %t_%s_%r.dbf

alter database archivelog;

alter database
add supplemental log
data for procedural replication;

select supplemental_log_data_pl
from v$database;

SUP
---
YES

alter database open;

Ça se complique quand il s’agit de vérifier que ça marche bien :

Option 1 : Utiliser LogMiner pour savoir si l’appel à la procédure est tracé dans le fichier redo log

On procède en 3 étapes et on utilise Log Miner en stockant le dictionnaire dans le redo log :

  • Enregistrer le dictionnaire dans les redo logs et notez la première archive utile :
EXECUTE DBMS_LOGMNR_D.BUILD( -
OPTIONS=> DBMS_LOGMNR_D.STORE_IN_REDO_LOGS);

SELECT NAME FROM V$ARCHIVED_LOG WHERE sequence# in (
select max(sequence#) from V$ARCHIVED_LOG where DICTIONARY_BEGIN='YES');

NAME
--------------------------------------------------------
/u02/app/oracle/oradata/ORCL/archives/1_38_630213449.dbf
  • Générer l’appel à la procédure que l’on va essayer de retrouver. Sous le schéma SCOTT, exécutez les opérations suivantes (Les ordres insert et delete permettent de delimiter la zone du Redo dans laquelle on recherchera l’appel à la procédure) :
connect scott/tiger

create or replace procedure gark(a number) is
begin
null;
end;
/

sqlplus scott/tiger

select sid, serial#
from v$session
where audsid=SYS_CONTEXT('USERENV', 'SESSIONID');

SID SERIAL#
--- ----------
125 146


insert into dept values (17,'GG','GG');

commit;

call gark(10);

delete from dept where deptno=17;

commit;

alter system archive log current;

  • Enregistrer ensuite les fichiers à examiner avec Log Miner et interroger la vue V$LOGMNR_CONTENTS pour retrouver les informations avec LogMiner :
select name
from v$archived_log
where sequence# in (select max(sequence#)
from v$archived_log
where dest_id=1)
and dest_id=1;

NAME
--------------------------------------------------------
/u02/app/oracle/oradata/ORCL/archives/1_39_630213449.dbf

EXECUTE DBMS_LOGMNR.ADD_LOGFILE( -
LOGFILENAME => -
'/u02/app/oracle/oradata/ORCL/archives/1_38_630213449.dbf',-
OPTIONS => DBMS_LOGMNR.NEW);

EXECUTE DBMS_LOGMNR.ADD_LOGFILE( -
LOGFILENAME => -
'/u02/app/oracle/oradata/ORCL/archives/1_39_630213449.dbf');

select filename from V$LOGMNR_LOGS;

FILENAME
--------------------------------------------------------
/u02/app/oracle/oradata/ORCL/archives/1_38_630213449.dbf
/u02/app/oracle/oradata/ORCL/archives/1_39_630213449.dbf


EXECUTE DBMS_LOGMNR.START_LOGMNR(-
OPTIONS => DBMS_LOGMNR.DICT_FROM_REDO_LOGS)

accept sid prompt "Enter Session ID: "
125
accept serial prompt "Enter Session Serial#: "
146
col operation format a8
select scn,
operation,
object_id
session#,
serial#,
redo_value, username
from v$logmnr_contents
where session#=&sid
and serial#=&serial;

SCN OPERATIO SESSION# SERIAL# REDO_VALUE
---------- -------- ---------- ---------- ----------
1090276 START 125 146 19070
1090276 INSERT 125 146 19072
1090278 COMMIT 125 146 19074
1090292 START 125 146 19076
1090278 COMMIT 125 146 19074
1090292 DELETE 125 146 19078
1090292 INTERNAL 125 146 19080
1090294 COMMIT 125 146 19082

exec DBMS_LOGMNR.END_LOGMNR

Après plus d’investigation, il ne semble pas que ni l’opération INTERNAL ni aucune autre operation entre l’insert et le delete ne corresponde à l’appel de la procédure.

Option 2 : « Dumper » le fichier LOG

Vous pouvez générer un DUMP du fichier log :

alter system dump logfile
'/u02/app/oracle/oradata/ORCL/archives/1_39_630213449.dbf';

Là encore je n’ai pas trouvé non plus malgré cet excellent papier. Le fichier est quant à lui dans le sous-repertoire >diagnostic_dest</diag/rdbms/>DB_NAME</>INST_NAME</trace

Avant de conclure

désactivez la clause de SUPPLEMENTAL LOG et éventuellement le mode ARCHIVELOG avec le script ci-dessous :

alter database
drop supplemental log
data for procedural replication;

select supplemental_log_data_pl
from v$database;

SUP
---
NO

shutdown immediate;

startup mount;

alter database noarchivelog;
alter database open;

Conclusion :

Mauvais jour pour moi ; je réessaierai plus tard mais sans doute que vous aurez trouvé avant moi. Si c’est le cas, merci de me l’indiquer ;). Ce que je me demande encore c’est :

  • Est-ce qu’il ne faut pas faire autre chose comme marquer la fonction avec une procédure PL/SQL comme c’est le cas avec la réplication procédurale actuelle ?
  • Est-ce que j’ai les yeux en face des trous et je n’aurais pas laissé l’ordre dans le dump du redolog ?
  • En l’état, est-ce que cette fonctionnalité a un intérêt quelconque ?
  • Est-ce que tout simplement ce n’est pas une lacune de la version actuelle ?

Pour en savoir plus et faire fonctionner cette fonctionnalité, la documentation manque, elle aussi, parfois, de précision :