Oracle Streams : Paramètrer la réplication mono-directionelle d’une table
Si vous cherchez un moyen pour démarrer rapidement avec Oracle Streams, cet article et ceux qui suivront est pour vous ! Dans ce premier article, vous trouverez un exemple complet que vous pourrez mettre en oeuvre en moins de 30 minutes. C’est probablement la configuration la plus simple que vous trouverez : elle utilise une base de données, une table est répliquée dans un sens uniquement et vous utiliserez plusieurs raccourcis pour arriver à un résultat qui fonctionne sur Oracle 10g et 11g. Le fait de mettre en oeuvre une configuration complète d’Oracle Streams vous permettra de mettre le doigt sur une bonne partie des composants associés et vous mettra le pied à l’étrier, je vous le souhaite, pour des configurations plus riches. Alors surtout, laissez vos commentaires et vos idées pour les prochains articles…
Mais pourquoi un tel sujet ? D’abord, parce que j’ai eu la chance (ou la malchance) de travailler avec Streams sur de nombreux cas, parfois assez compliqués et sur des thèmes aussi variés que des migrations, la constitution d’environnements décisionnels ou d’architectures très distribuées. D’autre part, parce qu’Oracle a annoncé avant-hier le rachat de GoldenGate Software et que vous entendrez donc de plus en plus parler de BI temps réel, de rolling upgrades, y compris de vos applications, de très hautes disponibilité, de réplication hétérogène et d’une multitude d’autre sujets sur lesquels vous aurez sans doute l’opportunité de travailler avec Easyteam.Dans l’exemple qui suit, nous maintiendrons donc à jour une copié d’une table T1 située dans un schéma SOURCE dans une second schéma de la même base de données. Ce second schéma est nommé DESTINATION. Pour arriver à ce résultat, nous passerons par l’ensemble des étapes qui suivent:
- Construire un schéma et une table exemple
- Configurer les logs et le dictionnaire multi-versions de votre base de données
- Configurer l’administrateur et une file d’attente Streams
- Créer le process de capture et définir les règles associées
- Créer un process d’apply
- Transformer le SQL pour que les changements capturés sur le schéma
SOURCEsoient appliqués àDESTINATION - Instancier la table dans le schéma
DESTINATION - Démarrer les process de capture et d’apply
- Tester la réplication
- Arrêter et supprimer la configuration Oracle Streams
Note:
Cet article a été testé avec Oracle 11.1.0.7 et 10.2.0.4 Enterprise Edition sur Linux 32 bits.
Etape 1: Construire un schéma et une table exemple
Pour commencer, nous allons créer un schéma SOURCE et une table T1. Voici le script que vous pourrez lancer avec SQL*Plus ou SQL*Developer et qui permet d’effectuer ces opérations:
connect / as sysdba
create user source
identified by source
default tablespace users
temporary tablespace temp;
grant connect,resource to source;
connect source/source
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 les logs et le dictionnaire multi-versions de votre base de données
Les process de capture Oracle Streams utilisent le contenu des redologs et archivelogs pour construire un « Logical Change Records (LCR) », qui est un vecteur de changement encapsulé dans un type objet. Le LCR est ensuite propagé jusqu’à la destination grâce à des files d’attentes non-persistentes et qui résident en mémoire appelées « buffered queues ». Une fois propagés, les LCR sont appliqués sur la base de données destination grace aux process d’apply qui les transforment en ordres SQL.
Comme vous le savez les redologs ne contiennent pas les ordres SQL mais des données binaires qui permettent aux process de « recover » de reconstruire les changements effectués sur la base de données à partir d’une sauvegarde. De plus, ces redologs ne contiennent pas, par défaut, les informations nécessaires pour appliquer les changements sur une autre base de données que la base de données d’origine. Voici certaines des conséquences de ces 2 points:
- Les fichiers redologs ne permettent pas de reconstituer le SQL qui a été exécuté sur la base de données. Par exemple, pour les ordres DML, les informations contenues dans ces logs sont les rowid et les vecteurs de changement avec les images avant et après pour chacune des lignes impactées. Ainsi, si un unique ordre UPDATE modifie les valeurs d’une colonne pour plusieurs lignes sur le système source, Streams NE répliquera PAS cet ordre. A la place, les process de capture vont générer un LCR par ligne modifiée sur la source. Pour le dire autrement, un UPDATE sur la base de données source peut générer plusieurs millions de LCR et donc d’ordres UPDATE sur la base de données destination.
- Les rowid sont utilisés pour identifier de manière unique les lignes modifiées et ainsi permettre le recover des archivelogs et des redologs. Toutefois, les rowid sont différents entre la base de données source et la base de données destination, même si la seconde base de données a été créée, au départ, à partir d’une copie physique de la base de données source. Pour identifier de manière unique les lignes modifiées il faut donc s’appuyer sur un identifiant de chaque ligne comme une clé unique ou une clé primaire. Pour ajouter ces informations aux LCR, il faut les ajouter aux redologs; vous utiliserez les informations complémentaires dans les redologs avec les « supplemental logs ».
- Les schémas et les noms des objets modifiés ne sont pas stockés non plus dans les fichiers de redologs. A la place, l’information stockée est l’identifiant de l’objet associé. Ces identifiants sont stockés dans les LCRs et il faut donc une copie du dictionnaire de données sur la base de données destination pour transformer les LCRs en SQL sur la destination. La copie de ce dictionnaire est stocké dans le « Multi Version Data Dictionary (MVDD) ». Il doit être capturé sur la base de données source et envoyé sur la base de données destination. C’est le cas, même si la source et la destination sont la même base de données puisque dans le cas d’une commande DROP par exemple, l’objet sera supprimé du dictionnaire d’origine lorsque le LCR correspondant est transformé en SQL, d’où l’importance du MVDD.
Pour l’ensemble des raisons ci-dessus, vous devez préparer la base de données source avant de mettre en place les process de capture. En particulier, cette base de données doit être en mode ARCHIVELOG. Suivant la manière dont vous préparerez les objets, vous pouvez également ajouter le « supplemental logging » pour toute la base de données ou vous l’activerez au niveau de chaque objet répliqué. Comme nous voulons simplifier la mise en oeuvre, nous allons l’activer au niveau de la base de données. Ci-dessous le script qui active le supplemental logging:
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;
SUPPLEME SUP SUP
-------- --- ---
IMPLICIT YES YES
Vous pouvez ensuite capturer le dictionaire de données sur la source et le pousser sur la destination par l’intermédiaire des redologs grace à la procédure DBMS_CAPTURE_ADM.BUILD:
connect / as sysdba
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 = 49042254018
Il est important que noter le SCN retourné par la procédure DBMS_CAPTURE_ADM.BUILD. Vous utiliserez ce SCN comme « first SCN » du process de capture de sorte que les meta-données de la source puisse être poussé dans le MVDD de la destination. Il faut noter que seul les informations minimum pour démarrer Streams sont enregistrées dans le MVDD. Il faut également ajouter les méta-données pour chacun des objets que vous voulez répliquer un objet. Pour cela, vous utiliserez les procédures prepare_xxxx_instantiation du package dbms_capture_adm comme ci-dessous :
exec dbms_capture_adm.prepare_table_instantiation(-
table_name=>'source.t1');
Note:
dbms_capture_adm.prepare_table_instantiationpermet également de valider qu’il n’y a pas de modifications en cours sur la tableSOURCE.T1. Un verrou partagé est donc posé sur la table ce qui peut impacter significativement votre application au moment de l’utilisation de la procédure.
Etape 3: Configurer l’administrateur et une file d’attente Streams
Pour utiliser Streams, vous devez créer un administrateur Streams dans toutes les bases de données impliquées dans la réplication et tous les process de capture, propagation et apply associés; le script qui suit crée cet administrateur. Il est recommandé de créer un tablespace séparé pour stocker les files d’attente car l’utilisation d’une file d’attente dans un tablespace empêche la procédure de tablespace « point in time recovery ». Ensuite, créez un utilisateur STRMADMIN, affectez-lui les privilèges, les roles ainsi que les files d’attentes qui permettront aux process de capture et d’apply de partager les LCR:
connect / as sysdba
CREATE TABLESPACE streams_tbs DATAFILE
'/u01/app/oracle/oradata/BLACK/streams_tbs.dbf'
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 le process de capture et définir les règles associées
Une fois les bases de données source et destination paramétrées, vous pouvez créer un process de capture et ajouter la table source à ce process. Le paramètre first_scn doit correspondre à la valeur retournée par la procédure DBMS_CAPTURE_ADM.BUILD; le paramètre source_database doit correspondre au paramètre db_unique_name de la base de données source ou db_name, si db_unique_name n’est pas utilisé; voici le script qui créé le process de capture:
accept first_scn prompt "Enter the First SCN of the Capture: "
connect strmadmin/strmadmin
Enter the First SCN of the Capture: 49042254018
var first_scn number;
exec :first_scn:=&&first_scn
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 => :first_scn,
logfile_assignment => 'implicit');
END;
/
col capture_name format a15
col queue_name format a13
col first_scn format 999999999999
col start_scn format 999999999999
col rule_set_name format a11
select capture_name,
queue_name,
first_scn,
start_scn,
rule_set_name
from dba_capture;
CAPTURE_NAME QUEUE_NAME FIRST_SCN START_SCN RULE_SET_N
--------------- ------------- ------------- ------------- ----------
STREAMS_CAPTURE STREAMS_QUEUE 49042254018 49042254018
BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name => 'source.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 rule_owner,
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 SOURCE T1 DML T16
Etape 5: Créer un process d’apply
Vous devez ensuite créer un process d’apply qui va souscrire à la file d’attente utilisée par le process de capture et appliquer les changements de la table SOURCE.T1:
connect strmadmin/strmadmin
BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name => 'source.t1',
streams_type => 'apply',
streams_name => 'streams_apply',
queue_name => 'strmadmin.streams_queue',
include_dml => true,
include_ddl => false,
include_tagged_lcr => true,
source_database => 'BLACK',
inclusion_rule => true);
END;
/
col apply_name format a13
col queue_name format a13
col rule_set_name format a11
select apply_name,
queue_name,
rule_set_name,
status,
message_delivery_mode
from dba_apply;
APPLY_NAME QUEUE_NAME RULE_SET_NA STATUS MESSAGE_DE
------------- ------------- ----------- -------- ----------
STREAMS_APPLY STREAMS_QUEUE RULESET$_10 DISABLED CAPTURED
Etape 6: Transformer le SQL pour que les changements capturés sur le schéma SOURCE soient appliqués à DESTINATION
Dans cet exemple, les bases de données source et destination sont la même base de données; les tables source et destination ne peuvent donc pas avoir le même nom et le même schéma. Vous allez ajouter une règle de transformation pour renommer le nom du schéma de l’objet que vous répliquez et trasnformer SOURCE en DESTINATION. Le script ci-dessous ajoute une régle de transformation au process d’apply:
connect strmadmin/strmadmin
col rule_name format a20 new_value rulename
select rule_owner,
STREAMS_NAME,
STREAMS_TYPE,
TABLE_OWNER,
TABLE_NAME,
RULE_TYPE,
RULE_NAME
from DBA_STREAMS_TABLE_RULES
where streams_name='STREAMS_APPLY'
and streams_type='APPLY'
and rule_type='DML';
prompt &&rulename
T16
begin
dbms_streams_adm.rename_schema(
rule_name => '&&rulename' ,
from_schema_name => 'SOURCE',
to_schema_name => 'DESTINATION',
step_number => 0,
operation => 'add');
end;
/
col rule_name format A6
col from_schema_name format a6
col to_schema_name format a12
select rule_name,
transform_type,
from_schema_name,
to_schema_name,
declarative_type
from dba_streams_transformations;
RULE_N TRANSFORM_TYPE FROM_S TO_SCHEMA_NA DECLARATIVE_T
------ -------------------------- ------ ------------ -------------
T16 DECLARATIVE TRANSFORMATION SOURCE DESTINATION RENAME SCHEMA
Etape 7: Instancier la table dans le schéma DESTINATION
Streams est désormais configuré. Avant de démarrer les différents process, vous devez instancier la table dans le schéma DESTINATION et stocker le SCN d’instanciation de sorte que le processus d’apply connaisse avec précision les changements appliqués sur cette table répliquée. Pour instancier la table, vous pouvez utiliser la méthode de votre choix et notamment RMAN, Datapump, exp ou Flashback query. Dans l’exemple qui suit, nous allons utiliser une flashback query. Comme la table destination réside dans la même base que la source, nous n’avons pas besoin de database link:
connect / as sysdba
create user destination
identified by destination
default tablespace users
temporary tablespace temp;
grant connect,resource to destination;
create table destination.t1(
id number primary key,
text varchar2(80));
col apply_scn format 999999999999 new_value instantiation_scn
select dbms_flashback.get_system_change_number apply_scn
from dual;
APPLY_SCN
-----------
49042261443
prompt Enter the Instantiation: &&instantiation_scn
Enter the Instantiation: 49042261443
insert into destination.t1
(select * from source.t1 as of scn &&instantiation_scn);
commit;
Une fois la table instanciée, utilisez la procédure dbms_apply_adm.set_table_instantiation_scn pour enregistrer le SCN d’instanciation et que le process d’apply n’applique les changements qu’à partir de ce point:
begin
dbms_apply_adm.set_table_instantiation_scn(
source_object_name => 'source.t1',
source_database_name => 'BLACK',
instantiation_scn => &&instantiation_scn);
end;
/
col SOURCE_DATABASE format a6
col OBJECT format a10
col INSTANTIATION_SCN format 999999999999
select source_database,
source_object_owner||'.'||source_object_name object,
instantiation_scn
from dba_apply_instantiated_objects;
SOURCE OBJECT INSTANTIATION_SCN
------ ---------- -----------------
BLACK SOURCE.T1 49042261443
Etape 8: Démarrer les process de capture et d’apply
Vous pouvez démarrer 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 la réplication
Pour tester la réplication, mettez à jour la table source et validez que les changements sont propagés sur la table destination. Voici un test simple qui montre que la réplication fonctionne comme il doit:
insert into source.t1(id, text)
values (3,'Text 3');
commit;
pause
col id format 99
col text format a6
select id,
text
from destination.t1;
ID TEXT
--- ------
1 Text 1
2 Text 2
3 Text 3
Déboguer la configuration Streams est au delà de ce premier article. Cependant, vous pouvez interroger les vues du dictionnaire des données pour connaître la configuration Streams et son statut.
Etape 10: Arrêter et supprimer la configuration Oracle Streams
Dans cette dernière étape, vous pouvez nettoyer l’environnement et le laisser tel qu’il était lorsque vous avez démarré. Pour ce faire, arrêtez et supprimez les process de capture et d’apply. Supprimez la file d’attente, l’administrateur Streams et le tablespace associé; supprimez également les 2 schémas et désactivez le « supplemental logging »:
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);
exec dbms_streams_adm.remove_queue('strmadmin.streams_queue',true,true);
drop user strmadmin cascade;
drop tablespace streams_tbs
including contents and datafiles;
drop user destination cascade;
drop user source cascade;
begin
for i in (select source_schema name
from dba_apply_instantiated_schemas
where source_schema in ('SOURCE','DESTINATION'))
loop
dbms_apply_adm.set_schema_instantiation_scn(
source_schema_name => i.name,
source_database_name => 'BLACK',
instantiation_scn => null);
end loop;
for i in (select source_object_owner||'.'||
source_object_name name
from dba_apply_instantiated_objects
where source_object_owner in ('SOURCE','DESTINATION'))
loop
dbms_apply_adm.set_table_instantiation_scn(
source_object_name => i.name,
source_database_name => 'BLACK',
instantiation_scn => null);
end loop;
end;
/
alter database drop supplemental log
data (primary key, unique index) columns;
select SUPPLEMENTAL_LOG_DATA_MIN,
SUPPLEMENTAL_LOG_DATA_PK,
SUPPLEMENTAL_LOG_DATA_UI
from gv$database;
SUPPLEME SUP SUP
-------- --- ---
NO NO NO




La procédure fonctionne bien en 10.2.0.4 mais juste un détail, la colonne ‘message_delivery_mode’ n’existe pas dans la vue dba_apply.
Merci pour cette initiation.
Olivier
Bonjour
La démarche est franchement géniale.
Un code claire et bien commenté.
Cepandant juste une question.
Le code se déroule étape par étape sans aucune err ora mais au final Rien; les modif de source reste en source.
Alors ou chercher ?
D’avance merci
C’est vraiment génant!
1) Quel est le statut de la capture
* qu’affiche la vue v$streams_capture; le process de capture peut mettre plusieurs minutes pour démarrer !
* qu’affiche la colonne status dans dba_capture ?
2) Y a-t-il une erreur dans dba_apply_error ? Quel est le status dans dba_apply
3) Je vous conseille pour en savoir plus (1) soit d’utiliser les scripts de Healthcheck de Streams ou maintenant le RDA comme décrit dans la note 273674.1 , soit (2) d’utiliser la fonctionnalité de tracking des messages comme décrit dans mon blog en anglais sur « Streams Tracking Streams Changes with V$STREAMS_MESSAGE_TRACKING »
N’hésitez pas à entrer en contact sur Twitter @Easyblogs ou @arkzoyd.
En réponse a vos questions
vue v$streams_capture
SID SERIAL#
106 510
CAPTURE# CAPTURE_NAME
1 STREAMS_CAPTURE
LOGMINER_ID STARTUP_TIME STATE
2 09.12.09 WAITING FOR DICTIONARY REDO: SCN 5119568
colonne status dans dba_capture =ENABLED
dba_apply_error = 0 Rows
le status dans dba_apply
STATUS
——–
ENABLED
ENABLED
ENABLED
3 rows selected
En espérant pouvoir y parvenir et en vous remerciant par avance
Hello guys,
I do confirm. It’s worked pretty well for me. Straight from the example, I’ve been able to configure a replication in less than 30 minutes.
Thank you so much for this tutorial. It rates 5 stars for me.
Cheers
Bonjour,
La procedure fonctionne parfaitement.
Merci pour l’explication claire et précise qui m’a permis de découvrir le processus de réplication.
Cependant, je voudrais savoir comment mettre en place la réplication en partant de la procédure si le user DESTINATION est sur une autre instance ?
Merci de votre réponse.