Eine CDC-Replikation stellt eine kostengünstig und einfach zu implementierende Lösung im Datawarehouse-Bereich dar um Daten zwischen verteilten Datenbanken zu Replizieren
Oracle CDC Replikation kann sowohl syncron als auch asyncron eingesetzt werden und stelle eine einfach zu implementierende Lösung für die Datenreplikation zwischen Oracle Datenbanken dar. CDC unterstützt dabei auch mehrere Consumer.
Im folgenden soll anhand eines Beispiels die Replikation einer Tabelle mittels eines syncronen CDC-Sets dargestellt werden. Für eine mit CDC zu replizierende Tabelle legt Oracle einen Change Table an, in dem alle Änderungen der zu replizierenen Basistabelle mitgeschrieben werden. Jeder Consumer erhält einen Subscribe-View, der die für ihn notwendigen Daten enthält. Jeder Consumer kann voneinander unabhängig seine bereits verarbeiteten (konsumierten) Daten aus dem View entfernen. Ausgangspunkt ist die Beispieltabelle DEPT, für die im nächsten Schritt eine ChangeTable angelegt wird, Löschen und Erweiterungen der Change Tabelle sind ebefalls als Beispiel angegeben.
select * from DEPT; DEPTNO DNAME LOC 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON
Das Erstellen eines Change Tables erfolgt über Oracle-interne Packages
declare begin dbms_cdc_publish.create_change_table( owner => 'DEPLOY', change_table_name => 'CLS_DEPT', change_set_name => 'SYNC_SET', source_schema => 'SCHEMA_OWNER', source_table => 'DEPT', column_type_list => ' DEPTNO NUMBER(2), DNAME VARCHAR2(14), LOC VARCHAR2(13)', capture_values=>'both', rs_id=>'Y', row_id=>'Y', user_id=>'N', timestamp=>'Y', object_id=>'N', source_colmap=>'N', target_colmap=>'N', options_string=>null); end;
Falls notwendig kann die so angelegte Tabelle wie folgt gelöscht oder geändert werden:
exec dbms_cdc_publish.drop_change_table('DEPLOY','CLS_DEPT','Y'); -- --Erweitern eines Change Tables um die Spalte Loc2 -- begin dbms_cdc_publish.alter_change_table( owner => 'DEPLOY', change_table_name => 'CL_DEPT', operation => 'ADD', column_list => 'LOC2 VARCHAR2(13)', rs_id=>'N', row_id=>'N', user_id=>'N', timestamp=>'N', object_id=>'N', source_colmap=>'N', target_colmap=>'N'); end;
Im nächsten Schritt erstellen wir eine Subscription und den zughörigen View. Dieser View sollte in einem Schema angelegt werden, auf welches der Subscriptionsuser Zugriff hat, es sollte nicht in dem Schema liegen, in dem sich der Change-Table befindet.
BEGIN DBMS_CDC_SUBSCRIBE.CREATE_SUBSCRIPTION( change_set_name => 'SYNC_SET', description => 'Change data for test', subscription_name => 'TEST'); END; /
Die neue Subscription kann wie folgt geprüft werden_
select * from DBA_SUBSCRIPTIONS; HANDLE SET_NAME USERNAME CREATED STATUS EARLIEST_SCN LATEST_SCN DESCRIPTION LAST_PURGED LAST_EXTENDED SUBSCRIPTION_NAME 1 SYNC_SET SCHEMA_OWNER 05.09.2009 09:56:21 N 1 0 Change data for test TEST
Der View für die Subscription wird wie folgt erstellt:
BEGIN DBMS_CDC_SUBSCRIBE.SUBSCRIBE( subscription_name => 'TEST', source_schema => 'SCHEMA_OWNER', source_table => 'DEPT', column_list => 'deptno, dname, loc', subscriber_view => 'V_SUBS_DEPT'); END; /
Oracle erstellt damit den folgenden View:
CREATE OR REPLACE VIEW deploy.v_subs_dept AS SELECT operation$, cscn$, commit_timestamp$, row_id$, rsid$, timestamp$, "DEPTNO", "DNAME", "LOC" FROM "SCHEMA_OWNER"."CLS_DEPT" WHERE cscn$ >= 1 AND cscn$ <= 0 WITH READ ONLY /
Das insert in die Basistabelle erstellt jetzt einen Record in der Change-Tabelle, dieser wird aber im Subscribtionsview erst nach Aufruf der Prozedure 'extent_windo' angezeigt:
Insert into DEPLOY.DEPT (DEPTNO, DNAME, LOC) Values (10, 'ACCOUNTING', 'NEW YORK'); COMMIT;
Dies ergibt einen Record in CLS_DEPT Chaneg Tabelle.
OPERATION$ CSCN$ COMMIT_TIMESTAMP$ RSID$ ROW_ID$ TIMESTAMP$ DEPTNO DNAME LOC I 281474976710655 01.01.4000 1 AAAbloAAFAAAHz2AAA 06.09.2009 16:53:34 50 IT EVERYWHER
Die Subscription muss explizit gestartet werden. Nach der Verarbeitung kann das Subscription-Window erweitert werden.
BEGIN DBMS_CDC_SUBSCRIBE.ACTIVATE_SUBSCRIPTION( subscription_name => 'TEST'); END; / BEGIN DBMS_CDC_SUBSCRIBE.EXTEND_WINDOW( subscription_name => 'TEST'); END; select * from DEPLOY.v_subs_dept OPERATION$ CSCN$ COMMIT_TIMESTAMP$ ROW_ID$ RSID$ TIMESTAMP$ DEPTNO DNAME LOC I 10151264490285 06.09.2009 16:58:54 AAAbloAAFAAAHz2AAA 06.09.2009 16:53:34 50 IT EVERYWHER
Nach erfolgreicher Verarbeitung der Daten kann das abgearbeitet Datenset (Subscription Window) gelöscht werden. Dies Wird über die PURGE_WINDOW Procedure erreicht.
BEGIN DBMS_CDC_SUBSCRIBE.PURGE_WINDOW( subscription_name => 'TEST'); END; /
Die Daten werden dabei aber nicht aus der CDC-Change Tabelle entfernt. Erst wenn alle Subscriber die Daten geladen haben kann die Change-Table mit einem separaten Procedure-Aufruf geleert werden. Vorsicht: in diesem Falle führt Oracle ein 'split Partition' Statement aus welches DML Befehle auf der Basistabelle kurzfristig blokieren. Diese Purge sollte also sehr regelmäßig (minimale Ausführungszeit, daher minimale Verzögerung) oder außerhalb der Zeiten stattfinden, in der die Basistabelle per DML verändert wird.
BEGIN dbms_cdc_publish.purge; END;