Oracle Advanced Replication – wie funktioniert`s

Werbung
Oracle Advanced Replication –
wie funktioniert’s ?
(Teil II – Updatable Materialized Views
oder Updatable Snapshot Replikation)
Autor: Stefan Menschel, ORACLE Deutschland GmbH
DOAGNews Q4_2004
Dieses Werk ist urheberrechtlich geschützt. Die dadurch begründeten Rechte, insbesondere die der Übersetzung, des Nachdrucks, des Vortrags, der Entnahme von Abbildungen
und Tabellen, der Funksendung, der Mikroverfilmung oder der Vervielfältigung auf anderen
Wegen und der Speicherung in Datenverarbeitungsanlagen, bleiben, bei auch nur
auszugsweiser Verwertung, vorbehalten. Eine Vervielfältigung dieses Werkes oder von
Teilen dieses Werkes ist auch im Einzelfall nur in den Grenzen der gesetzlichen
Bestimmungen des Urheberrechtes der Bundesrepublik Deutschland vom 9. September
1965 in der jeweils geltenden Fassung zulässig. Sie ist grundsätzlich vergütungspflichtig.
Zuwiderhandlungen unterliegen den Strafbestimmungen des Urheberrechtsgesetzes.
©2004
In diesem Artikel wird der Teil der symmetrischen Orale Realisation näher erläutern, welcher Update Anywhere DatenbankImplementierungen unterstützt. In der Entwicklung heutiger IT-Systeme wird immer öfter von Datenbankkonsolodierung und
zentralen Datenbanken gesprochen. Dennoch gibt es eine Reihe von Anwendungen, welche eine verteilt replizierte Datenbank
erfordern. Allein ein Aspekt der Security – Problematik für Internetdatenbankserver könnte mit Hilfe dieser Technologie ggf.
gelöst werden.
Was sind Updatable Materialized Views (UMV)?
Im ersten Kapitel wurde die einfache Replikation mit Hilfe der ReadOnly Materialized Views (RMV) erläutert. Auf der UMV
können nun DML-Operationen (INSERT/UPDATE/DELETE) im Gegensatz zur RMV ausgeführt werden. Die Grundlagen der
UMV stammen von den RMV. Dies bedeutet, dass die UMV ebenfalls wie die RMV die SQL*Net Konfiguration sowie
Datenbanklinks nutzt, um sich auf einem zentralen System (Masterdefinitionsite-MDS) zu registrieren. Zusätzlich sind nun
allerdings eine Reihe von Datenbankinternen Strukturen auf der MDS als auch auf der Datenbank der UMV erforderlich. Allein das
Thema „Transaktionskonflikt“ lässt erkennen, das hierfür zusätzliche Datenbankfunktionalitäten für ein solches System notwendig
sind.
In meinem Beispiel soll die Tabelle <DEPARTMENT> des User SCOTT über eine Updatable Materialized View auf die
Datenbanken DB_B.WORLD sowie DB_C.WORLD implementiert werden.
DEPARTMENT
DatabaseLink
DB_A.WORLD
MDS
DEPARTMENT
DatabaseLink
DEPARTMENT
DB_B.WORLD
UMV
DB_C.WORLD
UMV
Abb.1: Struktur Updatable Materialized Views
Voraussetzungen für die Implementierung der UMV auf der MDS
Alle im ersten Kapitel beschriebenen Komponenten gelten ebenfalls für die Implementierung der Updatable
Materialized Views. D.h. es müssen folgende Voraussetzungen geschaffen sein :
• SQL*Net Konfiguration, INIT*ORA Parameter
• Anlegen eines User REPADMIN auf allen Datenbanken, welcher intern die Replikation zwischen den
Datenbanksystemen vornimmt
• Anlegen von Materialized View Log für die Tabelle DEPARTMENT auf der Masterdefinitionsite im Schema
SCOTT (siehe auch Kapitel 1)
SQL>CONN scott/tiger@db_a.world
CREATE MATERIALIZED VIEW LOG ON department TABLESPACE snaplog;
Abb.2: SQL-Statement – Anlegen Materialized View Log
•
Festlegen des User REPADMIN als Propagator User und Vergabe folgender Grants
©2004
SQL>CONNECT SYS /PW@DB_A.WORLD AS SYSDBA;
EXEC DBMS_DEFER_SYS.REGISTER_PROPAGATOR('REPADMIN');
BEGIN
DBMS_REPCAT_ADMIN.REGISTER_USER_REPGROUP(
username
=>'REPADMIN’
privilege_type
=>'receiver'
list_of_gnames
=> NULL) ;
END;
/
EXEC DBMS_REPCAT_ADMIN.GRANT_ADMIN_ANY_REPGROUP(userid=>’REPADMIN');
,
,
GRANT EXECUTE ON DBMS_DEFER
TO REPADMIN;
GRANT EXECUTE ON DBMS_DEFER_SYS
TO REPADMIN;
GRANT EXECUTE ON DBMS_REPCAT_UTL2
TO REPADMIN;
GRANT EXECUTE ON DBMS_REPCAT
TO REPADMIN;
GRANT EXECUTE ON DBMS_DEFER_QUERY
TO REPADMIN;
GRANT EXECUTE ANY PROCEDURE
TO REPADMIN;
GRANT EXECUTE ON DBMSOBJGWRAPPER
TO REPADMIN;
GRANT EXECUTE ON DBMS_REPCAT_RPC
TO REPADMIN;
GRANT EXECUTE ON DBMS_DEFER_INTERNAL_SYS
TO REPADMIN;
GRANT LOCK ANY TABLE
TO REPADMIN;
GRANT INSERT ANY TABLE
TO REPADMIN;
GRANT UPDATE ANY TABLE
TO REPADMIN;
GRANT DELETE ANY TABLE
TO REPADMIN;
GRANT SELECT ANY DICTIONARY
TO REPADMIN;
GRANT SELECT ON SYS.SNAP_REFOP$
TO REPADMIN;
GRANT SELECT ANY TABLE
TO REPADMIN;
GRANT CREATE PUBLIC SYNONYM
TO REPADMIN;
GRANT DELETE ON DBA_REPCATLOG
TO REPADMIN;
GRANT ALTER SYSTEM
TO REPADMIN;
GRANT DELETE ON REG_SNAP$
TO REPADMIN WITH GRANT OPTION;
GRANT DELETE ON SLOG$
TO REPADMIN WITH GRANT OPTION;
GRANT DELETE ON MLOG$
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON DBA_REPGROUPED_COLUMN
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON SLOG$
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON MLOG$
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON REG_SNAP$
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON DBA_TAB_COLUMNS
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON DEFTRAN
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON DBA_REPCATLOG
TO REPADMIN WITH GRANT OPTION;
GRANT DELETE ON DBA_REPCATLOG
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON DEFCALL
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON DEFERROR
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON DBA_DB_LINKS
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON DBA_REPOBJECT
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON DBA_SNAPSHOTS
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON DBA_INDEXES
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON DBA_SEGMENTS
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON DBA_FREE_SPACE
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON DBA_TABLES
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON DBA_JOBS
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON DBA_JOBS_RUNNING
TO REPADMIN WITH GRANT OPTION;
GRANT SELECT ON v_$SESSION
TO REPADMIN WITH GRANT OPTION;
EXEC DBMS_REPCAT_ADMIN.GRANT_ADMIN_REPGROUP(userid=>'SCOTT');
GRANT EXECUTE ON DBMS_DEFER
GRANT EXECUTE ON SYS.DBMS_REPCAT_UTL2
GRANT SELECT ON sys.def$_error
GRANT EXECUTE ANY PROCEDURE
GRANT CREATE SYNONYM
TO scott;
TO scott;
TO scott;
TO scott;
TO scott;
Abb.3: SQL-Statements – Vergabe der Rechte
Implementierung der UMV-Unterstützung auf der MDS
Da es sich bei der UMV um eine symmetrische Replikation handelt, müssen zunächst auf der MDS die
Replikationsobjekte zu der zu replizierenden Tabelle <DEPARTMENT> angelegt werden. Zunächst wird eine
Masterrepgroup angelegt. Diese Mastergroup ist eine Sammlung von zu replizierenden Datenbankobjekten. In der
Regel werden alle Tabellen, welche logisch abhängig sind, in diese Groups gebündelt. Der Groupname ist für 30
Zeichen frei wählbar. Mit dem Parameter drop_contents = TRUE werden die zu dieser Mastergroup gehörenden
Replikationsobjekte gelöscht. Da dies im Normalfall nicht gewünscht ist, ist dieser Parameter mit FALSE (=Default)
zu belegen. Das Erstellen einer Mastergroup erzeugt automatisch einen Datenbankjob für die Verarbeitung der
©2004
administrativen Aufgaben. Bei einer Materialized View Replikation kann dieser im Anschluß nach der erfolgreichen
Implementierung wieder gelöscht werden, wenn ausschließlich Tabellen repliziert werden.
SQL>CONN repadmin/repadmin@db_a.world
BEGIN
DBMS_REPCAT.DROP_MASTER_REPGROUP(
gname
=>’UMV_GROUP1’ ,
drop_contents
=> FALSE
,
all_sites
=>FALSE
);
END;
EXEC DBMS_REPCAT.CREATE_MASTER_REPGROUP(gname =>'UMV_GROUP1');
Abb.4: SQL-Statement – Löschen und Anlegen Mastergroup
Anschließend wird nun die Tabelle <DEPARTMENT> als Replikationsobjekt definiert. Auch hier kann über den
Parameter drop_objects=TRUE entschieden werden, das Objekt (Tabelle DEPARTMENT) zu löschen. Default =
FALSE. Der Parameter use_existing_object definiert ob das Objekt auf der Zieldatenbank angelegt werden soll.
In unserem Fall wird die Tabelle DEPARTMENT auf der Datenbank DB_B.WORLD anderweitig angelegt. Der
Parameter copy_rows gibt an, ob Tabelleninhalte der Tabelle DEPARTMENT bei der Initialisierung der Replikation
von der Datenbank DB_A.WORLD zur Datenbank DB_B.WORLD gesendet werden sollen. Im Parameter gname
wird nun die Tabelle DEPARTMENT in die Mastergroup UMV_GROUP1 eingehangen.
SQL>CONN repadmin/repadmin@db_a.world
BEGIN
DBMS_REPCAT.DROP_MASTER_REPOBJECT(
sname
=>'SCOTT'
oname
=>'"DEPARTEMENT"'
type
=>'TABLE'
drop_objects =>FALSE
END;
BEGIN
DBMS_REPCAT.CREATE_MASTER_REPOBJECT(
sname
=>'SCOTT'
oname
=>'DEPARTMENT'
type
=>'TABLE'
use_existing_object => FALSE ,
ddl_text
=> NULL
comment
=> NULL
retry
=> TRUE
copy_rows
=> TRUE
gname
=>'UMV_GROUP1'
END;
,
,
,
);
,
,
,
,
,
,
,
);
Abb.5: SQL-Statement – Löschen und Anlegen Masterrepobject
Nach der Erstellung der Replikationsobjekte müssen diese für die Replikationsunterstützung generiert werden. Damit
werden für diese alle internen Replikationsobjekte generiert. U.a. sind dann folgende neuen Packages sichtbar.
DEPARTMENT$RP – Package sowie DEPARTMENT$RP – Package Body. Diese (RemoteProcedureCall-Packages)
sind für die Abarbeitung der Transaktionen auf der MDS, welche auf der UMV per DML entstanden und von dort an
die MDS gesendet werden. Wichtig bei dem Aufruf dieser Statements in Abb.5 und Abb.6 ist, das immer der gleiche
NLS_LANG – Parameter auf den Systemen verwendet wird, weil sonst u.U. eine falsche Sortierung innerhalb der
..$RP Packages vorkommen kann. Dann stimmen die gelieferten Werte mit den RPC nicht überein.
SQL>CONN repadmin/repadmin@db_a.world
BEGIN
DBMS_REPCAT.GENERATE_REPLICATION_SUPPORT(
sname
=>'SCOTT’
oname
=>'DEPARTMENT’
type
=>'TABLE'
gen_objs_owner
=>'REPADMIN'
END;
Abb.6: SQL-Statement – Generieren Replikationsunterstützung
©2004
,
,
,
);
Zum Abschluss ist nun die Mastergroup zu aktivieren und deren Status zu überprüfen.
SQL>CONN repadmin/repadmin@db_a.world
EXEC DBMS_REPCAT.RESUME_MASTER_ACTIVITY('UMV_GROUP1');
SELECT gname,status FROM dba_repcat;
GNAME
STATUS
-----------------------------------------------------------------UMV_GROUP1
NORMAL
Abb.7: SQL-Statement – Aktivieren Mastergroup
Implementierung der UMVs
Für die Nutzung einer UMV müssen auch auf den UMV-Datenbanken alle Rechte wie auf der MDS entsprechend
vergeben werden. (siehe Abb.3)
Nach dem Anlegen des Users Repadmin und der Vergabe der Rechte müssen nun für beide User Private Datenbank
Links in beide Richtungen angelegt werden.
•
Private Datenbank Links für die User SCOTT sowie REPADMIN in beide Richtungen
SQL>CONN scott/tiger@dba_a.world
CREATE DATABASE LINK DB_B.WORLD
CONNECT TO scott IDENTIFIED BY tiger
USING ’DB_B.WORLD’;
SQL>CONN scott/tiger@dba_b.world
CREATE DATABASE LINK DB_A.WORLD
CONNECT TO scott IDENTIFIED BY tiger
USING ’DB_A.WORLD’;
CONN repadmin/repadmin@db_a.world
CREATE DATABASE LINK DB_B.WORLD
CONNECT TO repadmin IDENTIFIED BY repadmin
USING ’DB_B.WORLD’;
CONN repadmin/repadmin@db_b.world
CREATE DATABASE LINK DB_A.WORLD
CONNECT TO repadmin IDENTIFIED BY repadmin
USING ’DB_A.WORLD’;
Abb.8: SQL-Statement – Anlegen Datenbank Link
Nun kann mit der Implementierung der UMV begonnen werden. Diese unterscheidet sich zunächst nur in einem
zusätzlichen Kommando gegenüber der RMV. Deshalb sind alle notwendigen Infos aus dem ersten Kapitel der RMV
auch hier zutreffend.
SQL>CONN scott/tiger@db_b.world;
CREATE MATERIALIZED VIEW department
ON PREBUILT TABLE
REFRESH FAST
WITH PRIMARY KEY
FOR UPDATE
AS SELECT * FROM department@db_a.world;
Abb.9: SQL-Statement – Anlegen Updatable Materialized View
Im Anschluss wird nun die Materialized View Group definiert. Diese ist das Gegenstück zur Mastergroup von der
MDS.
SQL>CONN repadmin/repadmin@db_b.world
BEGIN
DBMS_REPCAT.DROP_MVIEW_REPGROUP(
gname
=>'UMV_GROUP1'
drop_contents
=>FALSE)
END;
BEGIN
DBMS_REPCAT.CREATE_MVIEW_REPGROUP(
gname
=>'UMV_GROUP1'
master
=>'DB_A.WORLD'
propagation_mode
=>'ASYNCHRONOUS'
);
END;
Abb.10: SQL-Statement – Löschen und Anlegen Materialized View Group
©2004
,
;
,
,
Nun ist es noch erforderlich auf der Datenbank DB_B.WORLD die UMV als Replikationsobjekt zu erstellen. Der
Parameter min_communication ist auf TRUE zu setzen, um eine Reduzierung der Netzwerklast zu erreichen. In
diesem Fall werden ausschließlich geänderte Werte mit :old und :new sowie der Primary Key an die MDS gesendet.
SQL>CONN repadmin/repadmin@db_b.world
BEGIN
DBMS_REPCAT.CREATE_MVIEW_REPOBJECT(
sname
=>'SCOTT'
oname
=>'DEPARTMENT'
type
=>'MATERIALIZED VIEW'
gname
=>'UMV_GROUP1'
gen_objs_owner
=>'REPADMIN'
min_communication =>TRUE);
END;
,
,
,
,
,
Abb.11: SQL-Statement – Anlegen Materialized View Repobject
Es können verschiedene Tabellen in Refresh – Gruppen „gruppiert“ werden. Ratsam ist es, diese so zu gruppieren, wie
sie bereits in der Masterreplikationsgruppe (UMV_GROUP1) definiert werden. Wie diese Gruppierung vorgenommen
wird, ist im ersten Kapitel bei den RMV beschrieben. Ebenso ist im ersten Kapitel beschrieben, wie eine
Aktualisierung der UMV mit Daten von der MDS vorgenommen wird. Der Sinn einer UMV besteht aber nun darin,
dass auf dieser ebenfalls Änderungen möglich sind. Die UMV verhält sich also jetzt wie eine ganz normale Tabelle.
Alle DML-Transaktionen werden in der Tabelle SYSTEM.DEF$_AQCALL in der Datenbank DB_B.WORLD
gespeichert. Asynchrone Push/Refresh-Mechanismen – in der Regel Datenbankjobs – übernehmen nun die
Propagierung dieser Queue zur MDS (DB_A.WORLD).
Eine Transaktion kann ein Update auf 5000 Datensätze sein. Dann stehen 5000 Einträge in der Queue-Tabelle, denn es
wird jeder geänderte Datensatz als separater Call einer Transaction auf der MDS-nachgefahren. Dieses Transferieren
wird bei Ausführung des Commandos DBMS_REFRESH.REFRESH vorgenommen. Es kann jedoch auch ein zweiter
separater Datenbankjob diese Änderung in kürzeren Abständen zur MDS mit der Funktion
DBMS_DEFER_SYS.PUSH senden. Damit ist es möglich, in sehr kurzen Zeitabständen die DML-Transaktionen auf
einer UMV zur MDS zu propagieren. Wichtig ist im Gegensatz zu einer RMV, dass bei einer UMV in der Phase des
Refreshs ein LOCK Table ausgeführt wird. Wenn also 10 Tabellen in einer Refreshgruppe gruppiert wurden, so
werden bei Aufruf von DBMS_REFRESH.REFRESH alle 10 Tabellen in einen Table Lock versetzt. Dies kann u.U.
die Applikation behindern, wenn dieser Refresh in kurzen Intervallen ausgeführt wird.
Da es sich hierbei um eine asynchrone Replikation handelt, ist es immer möglich, dass Transaktionskonflikte
entstehen. Diese können enstehen, wenn der gleiche Datensatz von einem anderen Datenbanksystem (ebenfalls eine
UMV oder auf der MDS) bearbeitet wurde. Der Konflikt wird bei einer Materialized View Replikation immer auf der
MDS erkannt und muß dort aufgelöst werden. Wie wird dieser Konflikt erkannt? Die UMV propagiert immer die :old
und :new Werte der UMV + den Primary Key. Nun wird auf der MDS der Satz über den PK gesucht. Im Anschluß
wird der gefundene Satz mit allen Attributen mit den gelieferten :old Werten verglichen. Gibt es dabei eine
Abweichung, so kommt es zu einem Transaktionsfehler mit der Meldung ORA-01403 no_data_found. Für diese Fälle
ist vor der Implementierung einer Replikationsumgebung sehr intensiv zu analysieren, ob derartige Fehler auftreten
können, und wenn ja, wie damit umgegangen wird. Oracle liefert hierfür mehrere Konfliktlösungsroutinen gleich mit.
(TIMESTAMP,SITE PRIORITY, ADDITIVE,MINIMUM, MAXIMUM) Damit können automatische
Konfliktlösungen implementiert werden, welche diese Konflikte während des Auftretens sofort lösen. Für den Fall,
dass auf der MDS ein Satz gelöscht wurde gibt es jedoch keine automatische Lösung. Hier ist manuelle PL/SQLProgrammierung in eigenen Konfliktlösungen notwendig. Damit ist auch gesagt, dass DELETE-Transaktionen in
Replikationsumgebungen immer ein Problem darstellen. Deshalb sollten physikalische DELETE in logische DELETE
(Löschkennzeichen) umgewandelt werden.
Um die Replikation auf der Datenbank DB_C.WORLD aufzusetzen, ist genauso zu verfahren wie mit der Datenbank
DB_B.WORLD
©2004
Tipps und Tricks
Was wird nicht unterstützt für Replikation? geclusterte Tabellen, LONG+LONG RAW Datentyp, Sequences,
Replikation zwischen verschiedenen Schemas, es gibt keine Konfliktlösung für BLOB/CLOB – Datentypen
Was sind Connection-Qualifier ? Dies sind zusätzliche Namen bei der Definition des Datenbanklinks.
(z.B.DB_B.WORLD@UMV_GROUP1) So können über diese nun unter einem einzigen User mehrfache
Datenbanklinks zu einer Zieldatenbank genutzt werden, um ein paralleles Abarbeiten der Queue zu erreichen.
Wie ist das mit dem GLOBAL_NAME ? Der GLOBAL_NAME muß dem Namen des Datenbanklinks entsprechen
und muß in der TNS_NAMES.ORA gefunden werden. Zusätzlich ist der INIT*.ORA Parameter global_names=TRUE
zu setzen. Dies ist Voraussetzung für die Replikation.
Was passiert bei dem Refresh einer UMV ? Zunächst werden alle lokalen Änderungen aus der Queue
(SYSTEM.DEF$_AQCALL) an die MDS propagiert. Dort werden diese Änderungen auf der Tabelle nachgefahren.
Diese Änderung wiederum wird im Materialized View Log protokolliert, denn eine andere UMV soll diese Änderung
vielleicht ebenfalls bekommen. Im Anschluß wird auf der UMV diese eigene Transaktion nochmals ausgeführt. Der
Originalsatz wird zunächst gelöscht und danach wieder eingefügt. Dadurch entsteht bei den Materialized Views
höhere Last.
Wie ist das mit Triggern ? Bei allen Triggern auf replizierenden Tabellen sind Änderungen notwendig, weil der
Trigger erkennen muß, woher diese Transaktion kommt.
Dafür gibt es folgende Möglichkeit : IF NOT DBMS_REPUTIL.FROM_REMOTE THEN .... hier werden also keine
Replikationstransaktionen den Trigger aktivieren.
... und ForeignKeyConstraints ? Im Gegensatz zu früheren Oracle Releases können diese Constraints nun ab Oracle
Release 8.1 verwendet werden, sind jedoch als INITIALLY DEFERRED DEFERABLE zu deklarieren. Damit werden
die Constraints in der Refresh-Session für alle beteiligten Tabellen deaktiviert und anschließend wieder aktiviert.
Wie ist es mit Fragmentierungen ? UMV’s können ebenso wie die RMV’s horizontal und vertikal von der
Basistabelle aufgebaut werden. D.h. bestimmte Sätze und/oder nur bestimmte Columns können die Materialized View
bilden.
Wie ist es mit Export/Import ? Es ist dringend zu empfehlen folgende Tabellen aus dem Schema SYS zu exportieren
: SLOG$,MLOG$,REG_SNAP$, da diese bei einem Full-Datenbankexport nicht mit exportiert werden.
Benötigt die Materialized View Primary Key’s ? Jede Materialized View basiert auf einem Primary Key, dies ist
also unbedingt notwendig.
Kontakt:
[email protected]
©2004
Herunterladen