Oracle Streams B.A.-BA.

Il y a quelques jours, un post intitulée Migrer de 10g en 11g avec Zéro Indisponibilité et Streams, illustrait, sur ce blog, une utilisation d’Oracle Streams dans un cas particulier. Au vue des différents échanges sur le sujet, il semble utile de présenter un exemple plus simple que vous pourrez mettre en oeuvre en 30 minutes et qui donne une idée un peu plus précise de comment fonctionne Streams.

L’idée de l’exemple qui suit consiste à répliquer et maintenir synchronisée la copie d’une table T1 dans un autre schéma de la même base de données. L’intérêt d’un tel exemple réside surtout dans la simplicité de sa mise en oeuvre… mais passons aux choses concrètes.

Etape 1 : La table exemple

Pour commencer, il faut une table exemple. Le script ci-dessous crée le schéma DEMO et la table T1 que nous utiliserons dans la suite de cet exemple:

connect / as sysdba

create user demo
identified by demo
default tablespace users
temporary tablespace temp;

grant connect,resource to demo;

connect demo/demo

create table t1(
id number primary key,
text varchar2(80));

insert into t1(id, text)
values (1,'Text 1');

insert into t1(id, text)
values (2,'Text 2');

commit;

Etape 2 : Configurer la base de données

Avant de paramétrer Oracle Streams, il faut réunir un certain nombre de conditions (Au moins pour la capture à partir des fichiers redo/archive log) ; Il faut que la base de données soit une version Enterprise Edition et en mode archivelog. En outre, il faut ajouter des informations supplémentaires dans les fichiers log pour permettre de capturer les clés primaires/uniques et ainsi appliquer les modifications sur la table répliquée. Il est possible de forcer la capture de ces informations pour une table uniquement ; Pour simplifier, nous allons activer ce « SUPPLEMENTAL LOG » pour toute la base de données. Exécutez le script ci-dessous à cette fin :

connect / as sysdba

alter database add supplemental log
data (primary key, unique index) columns;

select SUPPLEMENTAL_LOG_DATA_MIN,
SUPPLEMENTAL_LOG_DATA_PK,
SUPPLEMENTAL_LOG_DATA_UI
from gv$database;

D’autre part, il faut pouvoir reconstruire les modifications à partir des fichiers de redo et ce, même si les structures d’origine ont été modifiée dans l’intervalle par un ordre DDL. Streams s’appuie sur une copie minimale du dictionnaire de données au moment du démarrage de la capture stockée dans le Multi-Version Data Dictionary (MVDD). Il faut donc capturer les informations minimales et les enregistrer dans les fichiers de redo logs avec la commande ci-dessous :

var first_scn number;

SET SERVEROUTPUT ON
DECLARE
scn NUMBER;
BEGIN
DBMS_CAPTURE_ADM.BUILD(
first_scn => scn);
DBMS_OUTPUT.PUT_LINE('First SCN Value = ' || scn);
:first_scn := scn;
END;
/

First SCN Value = 244468

La capture devra donc commencer avant la création de ces informations dans le redo log, d’où l’importance du first_scn lorsque vous créerez le process de capture. D’autre part, ces informations sont minimales et il vous faut également ajouter au MVDD, la définition des structures que vous voulez répliquer à l’aide des procédure prepare_xxx_instantiation du package dbms_capture_adm comme ci-dessous :

exec dbms_capture_adm.prepare_table_instantiation(-
table_name=>'demo.t1');


Etape 3 : Créer l’administrateur Oracle Streams

Pour créer les process et le règles associées à Streams, il faut créer un administrateur Streams pour votre base de données. Le script ci-dessous effectue les opérations associées et crée un tablespace (on suppose ici que les fichiers sont OMF), l’utilisateur, les privilèges et rôles associés ainsi qu’une file d’attente AQ qui sera utilisée par les process de capture et d’apply pour transporter les modifications :

connect / as sysdba

CREATE TABLESPACE streams_tbs
DATAFILE SIZE 25M
AUTOEXTEND ON MAXSIZE 256M;

CREATE USER strmadmin IDENTIFIED BY strmadmin
DEFAULT TABLESPACE streams_tbs
QUOTA UNLIMITED ON streams_tbs;

grant dba to strmadmin;

BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table => 'strmadmin.streams_queue_table',
queue_name => 'strmadmin.streams_queue');
END;
/


Etape 4 : Créer un process de capture

Vous allez maintenant aborder la création de votre configuration Streams proprement dites et commencer par créer un process de capture et ajoutez la table que vous voulez répliquer à ce process. Vous noterez dans ce qui suit, la valeur de first_scn inclut la capture du dictionnaire de données. Vous pouvez préciser le db_unique_name de la base de données (ou db_name si db_unique_name n’est pas utilisé) :

BEGIN
DBMS_CAPTURE_ADM.CREATE_CAPTURE(
queue_name => 'strmadmin.streams_queue',
capture_name => 'streams_capture',
rule_set_name => NULL,
source_database => 'BLACK',
use_database_link => false,
first_scn => 244468,
logfile_assignment => 'implicit');
END;
/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name => 'demo.t1',
streams_type => 'capture',
streams_name => 'streams_capture',
queue_name => 'strmadmin.streams_queue',
include_dml => true,
include_ddl => false,
include_tagged_lcr => true,
source_database => 'BLACK',
inclusion_rule => true);
END;
/

set lines 120
col streams_name format a16
col streams_type format a9
col table_owner format a10
col table_name format a15
col rule_type format a8
col rule_name format a15

select STREAMS_NAME,
STREAMS_TYPE,
TABLE_OWNER,
TABLE_NAME,
RULE_TYPE,
RULE_NAME
from DBA_STREAMS_TABLE_RULES;


STREAMS_NAME STREAMS_T TABLE_OWNE TABLE_NAME RULE_TYP RULE_NAME
---------------- --------- ---------- --------------- -------- ---------------
STREAMS_CAPTURE CAPTURE DEMO T1 DML T14

Etape 5 : Ajouter une règle de transformation au process de capture

Dans cet exemple, vous utilisez la même base de données pour la source et la destination de la réplication Streams et la table source et destination ne peuvent pas être la même. Par conséquent, vous devez ajouter une règle de transformation. Dans le script qui suit, nous allons copier la table demo.t1 dans copy.t1 :

begin
dbms_streams_adm.rename_schema(
rule_name => 't14' ,
from_schema_name => 'DEMO',
to_schema_name => 'COPY',
step_number => 0,
operation => 'add');
end;
/

Etape 6 : Créer un process d’apply

Un process d’apply doit également être créé. Celui-ci souscrit à la file d’attente utilisée pour stocker les modifications capturées et les applique sur la table copy.t1 :

connect strmadmin/strmadmin

Begin
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name => 'copy.t1',
streams_type => 'apply',
streams_name => 'streams_apply',
queue_name => 'strmadmin.streams_queue',
include_dml => true,
include_ddl => true,
include_tagged_lcr => true,
source_database => 'BLACK',
inclusion_rule => true);
END;
/

Etape 7 : Instancier la table

Cette opération consiste à créer la table copy.t1, copie de demo.t1 par la méthode de votre choix et à indiquer le SCN d’instanciation de cette table au process d’apply qui ne commencer à appliquer les modifications capturée sur la table source qu’à partir de ce SCN. Dans le script qui suit, la table copy.t1 est instanciée grâce la la fonctionnalité de flashback query:

connect / as sysdba

create user copy
identified by copy
default tablespace users
temporary tablespace temp;

grant connect,resource to copy;

create table copy.t1(
id number primary key,
text varchar2(80));

select dbms_flashback.get_system_change_number
from dual;

GET_SYSTEM_CHANGE_NUMBER
------------------------
246028

insert into copy.t1
(select * from demo.t1 as of scn 246028);

commit;

Une fois la table instanciée, la procédure set_table_instantiation_scn du package dbms_apply_adm definit le premier SCN d’apply :


begin
dbms_apply_adm.set_table_instantiation_scn(
source_object_name => 'demo.t1',
source_database_name => 'BLACK',
instantiation_scn => 246028);
end;
/

Etape 8 : Démarrer un process d’apply

La suite est simple; Démarrez les process de capture et d’apply :

exec dbms_capture_adm.start_capture('streams_capture');
exec dbms_apply_adm.start_apply('streams_apply');

Etape 9 : Tester Streams

Et effectuez un test du fonctionnement d’Oracle Streams

insert into demo.t1(id, text)
values (3,'Text 3');

commit;

pause

select * from copy.t1;

Si Streams ne fonctionne pas, vous pouvez interroger DBA_CAPTURE, V$STREAMS_CAPTURE, DBA_APPLY, DBA_APPLY_ERROR, DBA_STREAMS_TABLE_RULES ou V$BUFFERED_QUEUES.

Etape 10 : Arrêter et Supprimer la configuration Streams

Que votre test soit concluant ou que vous vouliez nettoyer votre configuration pour recommencer, voici comment supprimer les process de capture, d’apply et toutes les règles associées :

exec dbms_capture_adm.stop_capture('streams_capture');
exec dbms_apply_adm.stop_apply('streams_apply');

exec dbms_capture_adm.drop_capture('streams_capture',true);
exec dbms_apply_adm.drop_apply('streams_apply',true);

Et bien sur, vous pouvez aussi supprimer les tables et utilisateurs…