Introduction

Ce document suppose une connaissance de Streams dans son principe et ses possibilités. Bien que devenue obsolète en 12c Streams peut être intéressante pour disposer simplement d'un site de réplication. Mettre en place ce type de configuration n'est pas complexe à condition d'être très rigoureux, notamment dans l'utilisation des databases link.

L'objectif ici est de mettre en place une réplication streams bi-directionnelle entre deux bases Oracle 11gR2 nommées YODA et LUKE. Les deux bases sont sur 2 serveurs Linux distincts.

ora01 : 192.168.56.21 → base YODA

ora02 : 192.168.56.22 → base LUKE

L'OS des serveurs est CentOS 5.11. La version de Oracle est 11.2.0.4.

La réplication s'effectue sur un schéma nommé ALICE. Lors de la phase d'initialisation les données de ALICE présentent sur YODA seront importées dans LUKE.

Une fois la mise en place terminée, les modifications du schéma ALICE pourront se faire sur n'importe quelle base. Dans cet exemple aucune règle spécifique autre que celles par défaut ne sont implantées. Tous les ordres DML et DDL sont répliqués. Les deux schémas ALICE sur les deux bases sont donc identiques.

Création du user Streams

Pour la mise en place de streams il est conseillé de dédier un utilisateur à cette fonction. Cet utilisateur aura un privilège type DBA et sera nommé STRMADMIN.

Création des tablespaces dédiés à STRMADMIN sur YODA.

CREATE TABLESPACE "STRM_DATA" DATAFILE
'/u03/app/oracle/oradata/YODA/strm_data_01.dbf' SIZE 100M;
CREATE TEMPORARY TABLESPACE "STRM_TEMP" TEMPFILE
'/u02/app/oracle/oradata/YODA/strm_temp_01.dbf' SIZE 50M;

Création des tablespaces dédiés à STRMADMIN sur LUKE

CREATE TABLESPACE "STRM_DATA" DATAFILE
'/u03/app/oracle/oradata/LUKE/strm_data_01.dbf' SIZE 100M;
CREATE TEMPORARY TABLESPACE "STRM_TEMP" TEMPFILE
'/u02/app/oracle/oradata/LUKE/strm_temp_01.dbf' SIZE 50M;

Création du user STRMADMIN à faire sur les deux bases YODA et LUKE.

create user strmadmin identified by strmadmin default tablespace strm_data temporary tablespace strm_temp;

Affectation des droits pour STRMADMIN à faire sur les deux bases YODA et LUKE.

alter user strmadmin quota unlimited on strm_data;
grant dba to strmadmin;
execute dbms_streams_auth.grant_admin_privilege('STRMADMIN',TRUE);

Objet Directory

La première synchronisaton entre YODA et LUKE se fera via DataPump. Mettre en place sur chaque base un objet directory.

Sur YODA

mkdir -p /u02/app/oracle/dpump/YODA
sqlplus strmadmin/strmadmin@yoda
SQL> create directory dpump as '/u02/app/oracle/dpump/YODA';

Sur LUKE

mkdir -p /u02/app/oracle/dpump/LUKE
sqlplus strmadmin/strmadmin@luke
SQL> create directory dpump as '/u02/app/oracle/dpump/LUKE';

Paramètres Oracle

Il faut sur chaque bases activer le paramètre Oracle global_names à true.

alter system set global_names=true scope=both;

Création des files d'attente

Sur chaque base définir deux files d'attente. Une pour l'envoi vers l'autre base et l'autre pour la réception depuis l'autre base.

Sur les deux bases en strmadmin

begin
dbms_streams_adm.set_up_queue(
queue_table => 'file_envoi',
queue_name=> 'file_envoi');
end;
/
begin
dbms_streams_adm.set_up_queue(
queue_table => 'file_reception',
queue_name=> 'file_reception');
end;
/

Sur YODA les données seront envoyées dans file_envoi sur YODA pour être reçues, via l propagation, dans file_reception sur LUKE. Pour la réplication LUKE → YODA le principe est identique.

Création des databases link

Très important, en raison du positionement de global_names à true, les dblinks doivent avoir le même nom que la chaine Oracle*Net ( tnsnames.ora ).

Depuis YODA → LUKE

CREATE DATABASE LINK LUKE
CONNECT TO STRMADMIN IDENTIFIED BY strmadmin
USING 'LUKE';

Depuis LUKE → YODA

CREATE DATABASE LINK YODA
CONNECT TO STRMADMIN IDENTIFIED BY strmadmin
USING 'YODA';

Préparation des instanciations

Sur les deux bases.

begin
dbms_capture_adm.prepare_schema_instantiation(
schema_name=>'ALICE', supplemental_logging => 'keys');
end;
/

Cette action est indispensable afin d'activer pour le logminer le SUPPLEMENTAL LOGGING.

Création des captures

Sur YODA

begin
dbms_streams_adm.add_schema_rules(
schema_name=> 'ALICE',
streams_type=>'capture',
streams_name=>'CAPTURE_YODA',
queue_name=>'file_envoi',
include_dml=>true,
include_ddl=>true,
include_tagged_lcr=>false,
source_database=>'YODA');
end;
/

Sur LUKE

begin
dbms_streams_adm.add_schema_rules(
schema_name=> 'ALICE',
streams_type=>'capture',
streams_name=>'CAPTURE_LUKE',
queue_name=>'file_envoi',
include_dml=>true,
include_ddl=>true,
include_tagged_lcr=>false,
source_database=>'LUKE');
end;
/

Création des propagations

Attention la définition de la propagation diffère selon le fait d'être en stand alone ou en RAC

Bases en Stand Alone

Propagation de YODA → LUKE

begin
dbms_streams_adm.add_schema_propagation_rules(
schema_name =>'ALICE',
streams_name=>'PROPA_TO_LUKE',
source_queue_name=>'file_envoi',
destination_queue_name=>'file_reception@luke',
include_dml=>true,
include_ddl=>true,
include_tagged_lcr=>false,
inclusion_rule=>true,
source_database=>'YODA',
queue_to_queue=>false
);
end;
/

Propagation de LUKE → YODA

begin
dbms_streams_adm.add_schema_propagation_rules(
schema_name =>'ALICE',
streams_name=>'PROPA_TO_YODA',
source_queue_name=>'file_envoi',
destination_queue_name=>'file_reception@yoda',
include_dml=>true,
include_ddl=>true,
include_tagged_lcr=>false,
inclusion_rule=>true,
source_database=>'LUKE',
queue_to_queue=>false
);
end;
/

Cas des RAC

La propagation ci-dessus est définie pour des bases stand alone, dans le cas d'une configuration RAC celle-ci doit être définie différemment. Il faut en effet activer une autre option, queue_to_queue, à la valeur TRUE ( dans le cas des stand alone cette valeur est à FALSE ). De plus il faut définir la notion d'instance primaire et secondaire au niveau des queues d'envoi.

Au cas où YODA et LUKE seraient des bases RAC, les propagations doivent avoir la forme suivante :

Propagation de YODA → LUKE

begin
dbms_propagation_adm.create_propagation(
propagation_name=>'PROPA_TO_LUKE',
source_queue=>'file_envoi',
destination_queue=>'file_reception',
database_link=>'LUKE',
queue_to_queue=>TRUE
);
end;
/

Propagation de LUKE → YODA

begin
dbms_propagation_adm.create_propagation(
propagation_name=>'PROPA_TO_YODA',
source_queue=>'file_envoi',
destination_queue=>'file_reception',
database_link=>'YODA',
queue_to_queue=>TRUE
);
end;
/

Association des queues d'envoi. A faire sur YODA et LUKE

begin
dbms_aqadm.alter_queue_table(
queue_table=>'file_envoi',
primary_instance=>1,
secondary_instance=>2 );
end;
/

Création des applications

Sur YODA : application des données de LUKE

begin
dbms_streams_adm.add_schema_rules(
schema_name=>'ALICE',
streams_type=>'apply',
streams_name=>'APPLICATION_FOR_LUKE',
queue_name=>'file_reception',
include_dml=>true,
include_ddl=>true,
include_tagged_lcr=>false,
source_database=>'LUKE'
);
end;
/

Sur LUKE : application des données de YODA

begin
dbms_streams_adm.add_schema_rules(
schema_name=>'ALICE',
streams_type=>'apply',
streams_name=>'APPLICATION_FOR_YODA',
queue_name=>'file_reception',
include_dml=>true,
include_ddl=>true,
include_tagged_lcr=>false,
source_database=>'YODA'
);
end;
/

Instanciation des bases

Instanciation de YODA

set serveroutput on size 1000000
declare
current_scn number;
begin
current_scn:=dbms_flashback.get_system_change_number();
dbms_output.put_line( 'SCN Courant : ' || current_scn );
begin
dbms_apply_adm.set_schema_instantiation_scn@luke(
source_schema_name=>'ALICE',
source_database_name=>'YODA',
instantiation_scn=>current_scn,
recursive=>true
);
end;
end;
/

Instanciation de LUKE

set serveroutput on size 1000000
declare
current_scn number;
begin
current_scn:=dbms_flashback.get_system_change_number();
dbms_output.put_line( 'SCN Courant : ' || current_scn );
begin
dbms_apply_adm.set_schema_instantiation_scn@yoda(
source_schema_name=>'ALICE',
source_database_name=>'LUKE',
instantiation_scn=>current_scn,
recursive=>true
);
end;
end;
/

Import des données

Il s'agit ici d'utiliser datapump via un database link afin d'importer depuis YODA dans LUKE les informations du schéma ALICE.

Dans un premier temps il faut relever sur YODA le SCN courant.

select dbms_flashback.get_system_change_number() from dual;
-> 855547

Ce numéro SCN servira de marqueur lors de l'import DataPump via la clause flashback_scn. Créer un fichier de paramètres, alice.dpimp, pour l'import. Il est supposé créé sur chaque base la directory dpump.

directory=dpump
network_link=yoda
logfile=alice.dpimp.log
table_exists_action=truncate
schemas=alice
flashback_scn=855547
parallel=8

Oracle conseille de lancer en parallèle un nombre de processus égal à deux fois le nombre de coeurs soit pour un quad core → 8 processus.

Lancer ensuite l'import DataPump sur LUKE.

impdp strmadmin/strmadmin@luke parfile=alice.dpimp

Lancement des captures

Sur YODA

begin
dbms_capture_adm.start_capture('CAPTURE_YODA');
end;
/

Sur LUKE

begin
dbms_capture_adm.start_capture('CAPTURE_LUKE');
end;
/

Lancement des propagations

Sur LUKE

begin
dbms_propagation_adm.start_propagation(propagation_name=>'PROPA_TO_YODA');
end;
/

Sur YODA

begin
dbms_propagation_adm.start_propagation(propagation_name=>'PROPA_TO_YODA');
end;
/

Lancement des applications

Sur YODA

begin
dbms_apply_adm.start_apply('APPLICATION_FOR_LUKE');
end;
/

Sur LUKE

begin
dbms_apply_adm.start_apply('APPLICATION_FOR_YODA');
end;
/

Arrivé à ce stade la réplication bi-directionnelle en streams est opérationnelle.