2009-06-08 20 views
6

Wir sind dabei, Side-by-Side-Tests durchzuführen, um ein Altsystem mit einer neuen, glänzenden Version zu vergleichen. Wir haben eine Oracle-Datenbanktabelle, A, die Daten für das Altsystem speichert, und eine entsprechende Tabelle, B, die Daten für das neue System speichert, so dass die Datenbank für die Dauer des Tests denormalisiert wird. (Das Legacy-System und die Tabelle A sind ebenfalls festgelegt. Es sind keine Änderungen zulässig.)Tabellen in Oracle synchronisieren

Ich möchte, dass die seltenen DML-Operationen auf A sich auf B ausbreiten und umgekehrt. Ich habe mit einem Paar von Triggern begonnen, um das zu tun, aber ich habe das offensichtliche Problem festgestellt, dass die Tabellen mutieren, wenn die Trigger ausgeführt werden, und eine Ausnahme ausgelöst wird.

Gibt es eine Standardbehandlung dieses Problems? Ich habe unterschiedliche Berichte lesen, ob oder nicht mit dbms_scheduler ist der Weg zu gehen ...

Danke,

Andy

Update: Ich habe chickening aus dem ganzen endete ausstellen und sicherstellen, dass alle gespeicherten Prozeduren, die A aktualisieren, auch B aktualisieren, und umgekehrt.

Ich habe Quassnois Antwort als akzeptiert markiert, weil ich seinen Vorschlägen folgen würde, wenn ich in Zukunft mit dem gleichen Problem konfrontiert werde.

Ich habe JosephStyons Antwort markiert, weil ich kurz funktionierte, indem ich zwei Insert-/Update-Anweisungsebenen-Trigger für die Tabellen A und B hinzufügte und dann seine Merge-Prozedur mit A oder B als Master-Tabelle ausführte trigger ran (obwohl ich zuerst überprüft habe, dass die Zieltabelle durch die Zusammenführung geändert wird, wenn nicht, dann wird die Zieltabelle geändert).

+0

@Andy: Wenn Ihre Legacy-Anwendung gespeicherte Prozeduren verwendet, um die Tabellen zu aktualisieren, dann um Gottes Willen einfach Ihre Logik in die Verfahren, da es genau so ist, wie es sein sollte. Meine Ratschläge sind nur für die schlecht entwickelten Anwendungen gut, die DML-Anweisungen ausgeben (anstatt die Prozeduren aufzurufen), um die Daten zu aktualisieren. – Quassnoi

Antwort

3

würde ich A und B als Ansichten über eine einzige normalisiert (oder denormalized) Tabelle erstellen, und erstellt einen INSTEAD OF Trigger über diese Ansichten DML Operationen zu behandeln.

Wenn die Abfrage Angelegenheit plant, ist es besser, zwei Kopien von Tabellen zu halten: A_underlying und B_underlying und schaffen die Ansichten wie folgt aus:

CREATE VIEW A 
AS 
SELECT * 
FROM A_underlying 

CREATE VIEW B 
AS 
SELECT * 
FROM B_underlying 

Die Prädikate werden in die Ansichten geschoben werden, und die Abfragepläne für tatsächliche Tabellen und Ansichten werden die gleichen sein.

In INSTEAD OF Trigger über beide Ansicht, sollten Sie die Daten in beide zugrunde liegenden Tabellen legen.

+0

das ist eigentlich eine sehr nette Idee. Leider sind die Legacy-Anwendung und das Datenbankschema festgelegt. Ich habe die Frage aktualisiert, um dies zu berücksichtigen. Vielen Dank. – Andy

+0

Das Datenbankschema bleibt für die Außenwelt gleich. Sie können sogar die zugrunde liegenden Tabellen in einem anderen Schema erstellen. Durch das Erstellen der Trigger ändern Sie Ihr Schema nicht weniger als durch das Erstellen von Ansichten über zugrunde liegende Tabellen. – Quassnoi

+0

wahr. Um genauer zu sein: Ich kann Trigger hinzufügen, ohne das Legacy-System zu beeinträchtigen. Wenn ich eine Ansicht auf eine einzelne vereinheitlichte Tabelle AB erstellen wollte, müsste ich die Legacy-Anwendung ändern, um die Ansicht darauf zu verwenden. – Andy

1

die folgenden drei Anweisungen in einer gespeicherten Prozedur setzen, dann es als eine geplante Aufgabe ausgeführt, so oft wie Sie wollen:

--Assume that "A" is a master, and "B" needs to be synched 

--If no match in "A", delete from "B" 
DELETE FROM B 
WHERE NOT EXISTS(
       SELECT * 
       FROM A 
       WHERE A.PRIMARY_KEY = B.PRIMARY_KEY 
       ); 

--If there is a match, but they are different, then update "B" 
update 
    (
    select 
    a.field1 as new_value1 
    ,b.field1 as old_value1 
    ,a.field2 as new_value2 
    ,b.field2 as old_value2 
    ,.... 
    ,a.fieldN as new_valueN 
    ,b.fieldN as old_valueN 
    from 
    a 
    ,b 
where a.primary_key = b.primary_key 
) 
set 
    old_value1 = new_value1 
,old_value2 = new_value2 
,.... 
,old_valueN = new_valueN; 


--if the record is new to "A", then insert it into "B" 
INSERT INTO B 
SELECT * 
FROM A 
WHERE NOT EXISTS(
       SELECT * 
       FROM B 
       WHERE B.PRIMARY_KEY = A.PRIMARY_KEY 
       ); 
+0

Hallo Joseph. Zwischen den Tabellen besteht keine Master/Slave-Beziehung. Änderungen an A sollten sich nach B ausbreiten und umgekehrt. Ich nehme an, ich könnte Ihrem Code einen Zeitstempel hinzufügen, um dies zu erreichen, da Änderungen vom Benutzer initiiert werden und Probleme mit Nebenläufigkeit unwahrscheinlich sind. Vielen Dank. – Andy

1

Oracle 10g und haben über Änderungsmitteilung als asynchroner Prozess implementiert. Es ist automatisch und das Paket ist mit der Server-Installation von Oracle 10g und höher enthalten.

Sie können here für einige Informationen sehen.

Verwandte Themen