2009-06-08 22 views
6

Estamos a punto de realizar pruebas una al lado de la otra para comparar un sistema heredado con una nueva versión brillante. Tenemos una tabla de base de datos Oracle, A, que almacena datos para el sistema heredado, y una tabla equivalente, B, que almacena datos para el nuevo sistema, por lo que durante la prueba, la base de datos se desnormaliza. (Además, el sistema heredado y la tabla A son fijos, no se permiten cambios)Mantener las tablas sincronizadas en Oracle

Lo que quiero hacer es permitir que las operaciones DML infrecuentes en A se propaguen a B, y viceversa. Empecé con un par de factores desencadenantes para hacer esto, pero di con el problema obvio de que cuando se ejecutan los desencadenantes, las tablas están mutando y se produce una excepción.

¿Existe una forma estándar de manejar este problema? He leído diferentes informes sobre si es o no el uso de DBMS_SCHEDULER es el camino a seguir ...

Gracias,

Andy

Actualización: he terminado rajándose del conjunto problema y se aseguró de que todos los procedimientos almacenados que actualizan A, también actualicen B, y viceversa.

He marcado la respuesta de Quassnoi como aceptada, porque seguiría sus sugerencias si tuviera el mismo problema en el futuro.

He marcado la respuesta de JosephStyon, porque brevemente hice funcionar las cosas agregando dos disparadores de nivel de instrucción de inserción/actualización en las tablas A y B, luego haciendo su procedimiento de fusión usando A o B como la tabla maestra, dependiendo de disparador se ejecutó (aunque primero verifiqué que la tabla objetivo se cambiaría por la combinación, obteniendo si no).

+0

@Andy: si su aplicación heredada usa procedimientos almacenados para actualizar las tablas, entonces, por el amor de Dios, simplemente ponga su lógica en los procedimientos, ya que es exactamente como debería ser. Mis consejos son buenos solo para las aplicaciones poco desarrolladas que emiten declaraciones DML (en lugar de llamar a los procedimientos) para actualizar los datos. – Quassnoi

Respuesta

3

que crearía A y B como vistas de una sola tabla normalizada (o sin normalizar), y ha creado un disparador INSTEAD OF sobre estos puntos de vista para manejar DML operaciones.

Si la consulta tiene previsto importa, es mejor mantener dos copias de tablas: A_underlying y B_underlying y crear las vistas simplemente como esta:

CREATE VIEW A 
AS 
SELECT * 
FROM A_underlying 

CREATE VIEW B 
AS 
SELECT * 
FROM B_underlying 

Los predicados serán empujados a las vistas y los planes de consulta para tablas y vistas reales serán las mismas.

En INSTEAD OF desencadena en ambas vistas, debe colocar los datos en ambas tablas subyacentes.

+0

eso es realmente una muy buena idea. Desafortunadamente, la aplicación heredada y el esquema de la base de datos son fijos. He actualizado la pregunta para reflejar esto. Gracias. – Andy

+0

El esquema de la base de datos seguirá siendo el mismo para el mundo exterior. Incluso puede crear las tablas subyacentes en otro esquema. Al crear los desencadenadores, puede cambiar su esquema al crear vistas sobre las tablas subyacentes. – Quassnoi

+0

cierto. Para ser más específico: puedo agregar desencadenantes sin afectar el sistema heredado. Si quisiera crear una vista en una única tabla unificada AB, tendría que modificar la aplicación heredada para hacer uso de la vista sobre ella. – Andy

1

Ponga el siguiente tres declaraciones en un procedimiento almacenado, a continuación, ejecutarlo como un trabajo programado tan a menudo como desee:

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

Hola Joseph. No hay una relación maestro/esclavo entre las tablas. Los cambios en A deberían propagarse a B, y viceversa. Supongo que podría agregar una marca de tiempo a su código para lograr esto, ya que los cambios son iniciados por el usuario y los problemas de concurrencia son poco probables. Gracias. – Andy

1

Oracle 10g y anteriormente han implementado Notificación de cambio como un proceso asíncrono. Es automático y el paquete se incluye con la instalación del servidor de Oracle 10g y superior.

Puede ver here para obtener información.

Cuestiones relacionadas