La mejor manera de sincronizar datos entre dos bases de datos diferentes

24

Tengo que implementar la sincronización de datos entre dos grandes bases de datos que tienen estructuras completamente diferentes. Básicamente, necesito recopilar algunos datos sobre productos en diferentes tablas en la primera base de datos y reorganizarlos para otras tablas en la segunda base de datos.

Crear mis productos por primera vez no es muy complicado. Pero estoy buscando una manera de actualizar algunos datos específicos, no todos, sobre cada producto.

Obviamente, hay algunos problemas que hacen que esto sea complicado.

  • No se me permite hacer nada en la base de datos de origen, aparte de las consultas de selección.
  • En la base de datos de destino, puedo hacer consultas habituales (seleccionar, actualizar, insertar, crear) pero no puedo modificar la estructura / tablas existentes.
  • La base de datos de destino y fuente tienen estructuras completamente diferentes, las tablas no son iguales, por lo tanto, los datos realmente tienen que reorganizarse: la comparación de tablas no funcionará.
  • La base de datos de destino utiliza un servidor MySQL; la fuente puede ser DB2.
  • No hay campos de "hora actualizada" en ninguna parte.

Por lo tanto, todo el proceso debe hacerse en un solo script de Python (idealmente).

Pienso en crear un hash para cada producto, basado en los campos para actualizar en la base de datos de destino: md5 (código + descripción + proveedor + alrededor de otros 10 campos). A partir de la base de datos de origen se creará diariamente un nuevo hash basado en los mismos datos. Almacenaré todos los hashes en una sola tabla (código de artículo, current_hash, old_hash) para fines de rendimiento. Luego compare y actualice el producto si el nuevo hash es diferente del anterior.

Hay alrededor de 500 000 productos, así que estoy un poco preocupado por las actuaciones.

¿Es el buen camino a seguir?

Neow
fuente
2
¿Quieren que lo hagas con los ojos vendados también? Ese es mi problema en este momento ...
Capitán Hipertexto
1
@Ahora, ¿cómo te fue? ¿Algún consejo que puedas ofrecer ahora?
Edwin Evans
44
@EdwinEvans básicamente me quedé con mi primera idea, pero especialmente debido a las limitaciones que tenía. Mi script crea hash md5 basados ​​en datos clave para todos los elementos. Luego lo comparo con los hashes anteriores. Si los hashes son diferentes, carga todos los datos del elemento y actualiza todo. No estoy seguro si esta es la mejor manera, pero funciona de noche y las actuaciones son decentes.
Neow

Respuestas:

9

Esto es más o menos lo que he estado haciendo o viviendo en los últimos años, y mi instinto es que el tiempo para leer 500,000 artículos de la base de datos de origen y la sincronización en el destino no tomará tanto tiempo como uno podría pensar y el el tiempo necesario para leer los campos "clave", calcular el hash MD5 y realizar una verificación cruzada con su tabla para evitar la sincronización de elementos que no han cambiado no terminará ahorrando demasiado tiempo e incluso puede durar más. Simplemente lo leería todo y lo actualizaría todo. Si eso resulta en un tiempo de ejecución que es demasiado largo, entonces comprimiría el tiempo de ejecución haciendo que el ETL sea multiproceso, con cada subproceso operando solo en un segmento de la tabla pero trabajando en paralelo.

Sería importante asegurarse de que su base de datos de destino tenga un índice de clave principal o un índice único. De lo contrario, cada una de sus actualizaciones / inserciones podría bloquear toda la tabla. Esto sería malo si está adoptando el enfoque de subprocesos múltiples, pero importante incluso si permanece con un solo subproceso porque su trabajo podría bloquear la tabla de base de datos de destino e interferir con la aplicación que se encuentra encima de esa base de datos.

Usted dice que la base de datos "puede ser DB2". Cuando dice "puede", ¿implica que DB todavía se está diseñando / planificando? DB2 9 o superior tiene un seguimiento incorporado del último tiempo de actualización y la capacidad de consultar y recuperar solo los elementos que han cambiado desde un momento determinado. Quizás es por eso que el DB fue diseñado para no tener una columna que indique la última hora actualizada, por ejemplo:

SELECT * FROM T1 WHERE ROW CHANGE TIMESTAMP FOR TAB t1 > current timestamp - 1 hours;

El límite de la marca de tiempo para la consulta anterior sería la última marca de tiempo que ejecutó su sincronización.

Si este es el caso, eso debería resolver su problema. Sin embargo, su solución terminaría estando estrechamente vinculada a DB2 y, en el futuro, les gustaría pasar a otra plataforma de base de datos y esperar que su trabajo de sincronización no necesite ser revisado nuevamente. Por lo tanto, sería importante asegurarse de que todas las personas adecuadas sepan que su producto dependerá de permanecer en DB2, o si planean migrar esa migración incluiría la reestructuración de la base de datos para que tenga una columna de "último cambio de fecha y hora", y hacer lo que sea cambios necesarios en el nivel de la aplicación para llenar ese campo.

Thomas Carlisle
fuente
¿hay alguna solución similar para mysql también?
Fardin Behboudi
5

La sincronización de datos sería mucho mejor y más rápida, si se puede hacer sobre la base de algún tipo de identificador o indicador delta. Básicamente, debe actualizar las filas de datos de db de destino solo cuando no esté sincronizado con el db de origen.

En SQL Server DB, puede tomar la ayuda de Checksum fn también para construir el identificador basado en delta.

Debería desarrollar un trabajo basado en SQL para ser invocado a una determinada hora del día o de la noche para activar esta lógica SQL. Es mejor ejecutarlo como un trabajo nocturno de SQL, cuando el uso de db es muy bajo. Si el delta del origen y los registros db de destino no coinciden, solo extraiga esos registros. Pero la desventaja sería calcular la suma de verificación de las filas de datos de origen cada vez y luego compararla con los datos de destino.

Si tiene una columna como "LastModifiedDate" en las tablas de base de datos de origen, puede omitir el enfoque de suma de comprobación. De esta forma, su evaluación se ejecutará en la columna basada en la fecha y tomará menos tiempo en comparación con el enfoque de suma de verificación.

Karan
fuente
Gracias, pero no estoy seguro de que su solución pueda funcionar. Vea mis ediciones en la parte de "problemas".
Neow 01 de
Dado que no hay campos de tiempo actualizados en la base de datos de origen, entonces nos queda extraer las filas de datos calificadas en función de la suma de comprobación o el hash.
Karan
Ya que su fuente es db2. ¿Cómo intenta extraer los datos de él? a través de algún servicio web o API ..
Karan
Se ha configurado un dsn utilizando un controlador odbc. Puedo conectarme y hacer consultas usando pyodbc para Python.
Neow 01 de
Bien, esto es bueno, ya que puede realizar las consultas utilizando la herramienta llamada PyODBC en la base de datos remota. Puedes hacer una cosa más. Puede extraer los datos del producto directamente en el mismo formato que está en la nueva "Tabla de etapas" en su DB de destino sin ninguna verificación o validación. De esta manera, obtendrá los datos en vivo en una sola toma en su base de datos de destino debajo de las tablas del escenario. Luego, más adelante en el segundo paso, puede realizar las operaciones de suma de comprobación y actualizar los datos de la tabla transaccional de destino. Esto evitaría el hash o la evaluación de la suma de comprobación con los datos de la fuente db en tiempo real.
Karan
1

Usar un hash es una buena idea. Dado que la seguridad no es el objetivo en este caso, elija una función hash que sea rápida (md5 está bien).

A menos que planee dividir el cálculo de hash en múltiples subprocesos / procesos, realmente no necesita almacenar el valor de hash actual en la base de datos. Si su proceso es un solo script, solo tendrá el hash actual en la memoria y lo escribirá en la base de datos como el hash anterior después de haber actualizado los datos en la nueva base de datos.

Kent A.
fuente
-1

debería haber creado un servicio de Windows que se ejecutará en algunos momentos específicos cuando lo desee y encontrará los cambios en su base de datos de origen e insertará esos cambios en su base de datos de destino.

kumar viril
fuente
-1 (en realidad no voté negativamente, pero;) solo para Windows. no confiemos en ninguna arquitectura específica al desarrollar software, solo significa que solo unas pocas personas pueden usar sus cosas. la única constante es el cambio y lo que es mejor no confiar en cualquier plataforma específica en la medida en que hace las cosas más fáciles de mantener por sí mismo y para los usuarios
pythonian29033
1
@manish kumar la parte "encontrará los cambios en su base de datos fuente" es la más difícil.
Narvalex