2009-06-08 10 views
6

Za chwilę przeprowadzimy testy porównawcze, aby porównać starszy system z nową, błyszczącą wersją. Mamy tabelę bazy danych Oracle, A, która przechowuje dane dla dotychczasowego systemu, i równoważną tabelę, B, która przechowuje dane dla nowego systemu, więc w czasie trwania testu baza danych jest denormalizowana. (Także dotychczasowy system i tabela A są poprawione - nie można wprowadzać żadnych zmian)Prowadzenie tabel synchronizowanych w Oracle

Co chcę zrobić, to pozwolić nieczęstym operacjom DML na A propagować do B i na odwrót. Zacząłem od pary wyzwalaczy, aby to zrobić, ale natrafiłem na oczywisty problem, który powodował, że po uruchomieniu wyzwalaczy tabele mutują i generowany jest wyjątek.

Czy istnieje standardowy sposób radzenia sobie z tym problemem? Czytałem różne raporty na temat tego, czy za pomocą DBMS_SCHEDULER jest do zrobienia ...

Dzięki,

Andy

Aktualizacja: ja skończyło się chickening z całością wydać i upewnić się, że wszystkie procedury przechowywane, które aktualizują A, również aktualizacja B, i na odwrót.

Oznaczyłem odpowiedź Quassnoi jako zaakceptowaną, ponieważ będę postępować zgodnie z jego sugestiami, jeśli w przyszłości spotkają się z tym samym problemem.

Wyróżniłem odpowiedź JosephStyona, ponieważ krótko pracowałem, dodając dwa wyzwalacze poziomu wstawiania/aktualizacji na tabelach A i B, a następnie wykonując procedurę scalania używając A lub B jako tabeli głównej, w zależności od tego Trigger został uruchomiony (chociaż najpierw sprawdziłem, czy tabela docelowa zostanie zmieniona przez scalenie, wcześniej nie działa).

+0

@Andy: jeśli twoja starsza aplikacja korzysta z procedur przechowywanych w celu aktualizacji tabel, to na litość boską po prostu wprowadź swoją logikę do procedur, ponieważ tak właśnie powinno być. Moje porady są dobre tylko dla słabo opracowanych aplikacji, które wydają instrukcje DML (zamiast wywoływać procedury) w celu aktualizacji danych. – Quassnoi

Odpowiedz

3

będę tworzyć A i B jako widokiem na jednym znormalizowanego (lub nieznormalizowaną) stole i stworzyli INSTEAD OF spust nad tymi widokami obsłużyć DML operacje.

Jeśli zapytanie planuje sprawa, to lepiej, aby utrzymać dwie kopie tabel: A_underlying i B_underlying i tworzyć widoki po prostu tak:

CREATE VIEW A 
AS 
SELECT * 
FROM A_underlying 

CREATE VIEW B 
AS 
SELECT * 
FROM B_underlying 

Predykaty zostanie wepchnięta do poglądów i planów zapytań rzeczywiste tabele i widoki będą takie same.

W przypadku wywołania INSTEAD OF w obu widokach dane należy umieścić w obu tabelach podstawowych.

+0

to naprawdę bardzo fajny pomysł. Niestety, starsza wersja aplikacji i schemat bazy danych zostały naprawione. Zaktualizowałem pytanie, aby to odzwierciedlić. Dzięki. – Andy

+0

Schemat bazy danych pozostanie taki sam dla świata zewnętrznego. Można nawet utworzyć podstawowe tabele w innym schemacie. Tworząc reguły, zmieniasz schemat nie mniej niż tworząc widoki na tabelach podstawowych. – Quassnoi

+0

prawda. Bardziej szczegółowe: mogę dodawać wyzwalacze bez wpływu na dotychczasowy system. Gdybym chciał stworzyć widok na pojedynczą ujednoliconą tabelę AB, musiałbym zmodyfikować starszą aplikację, aby wykorzystała na nią widok. – Andy

1

Włóż poniżej trzech oświadczeń w procedurze przechowywanej, a następnie uruchomić go jako zaplanowane zadania tak często, jak chcesz:

--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

Cześć Joseph. Pomiędzy tabelami nie ma relacji master/slave. Zmiany A powinny propagować do B i na odwrót. Przypuszczam, że mógłbym dodać znacznik czasu do twojego kodu, aby to osiągnąć, ponieważ zmiany są inicjowane przez użytkownika, a problemy z współbieżnością są mało prawdopodobne. Dziękuję Ci. – Andy

1

Oracle 10g i powyżej wdrożyły Change Notification jak asynchronicznego procesu. Jest automatyczny, a pakiet jest dołączony do instalacji serwera Oracle 10g i nowszych.

Możesz zobaczyć here dla niektórych informacji.

Powiązane problemy