Il modo migliore per sincronizzare i dati tra due diversi database


24

Devo implementare la sincronizzazione dei dati tra due grandi database che hanno strutture completamente diverse. Fondamentalmente, ho bisogno di prendere alcuni dati sui prodotti in diverse tabelle nel primo database e riorganizzarli per altre tabelle nel secondo database.

Creare i miei prodotti per la prima volta non è molto complicato. Ma sto cercando un modo per aggiornare alcuni dati specifici - non tutti i dati - su ciascun prodotto.

Ovviamente, ci sono alcuni problemi che lo rendono difficile.

  • Non sono autorizzato a fare nulla sul database di origine a parte le query di selezione.
  • Sul database di destinazione, posso fare le solite query (selezionare, aggiornare, inserire, creare) ma non posso modificare la struttura / le tabelle esistenti.
  • Target e sorgente db hanno strutture completamente diverse, le tabelle non sono affatto le stesse, quindi i dati devono essere riorganizzati - il confronto delle tabelle non funzionerà.
  • Il database di destinazione utilizza un server MySQL - l'origine potrebbe essere DB2.
  • Non ci sono campi "tempo aggiornato" da nessuna parte.

Quindi l'intero processo deve essere eseguito in un singolo script Python (idealmente).

Penso alla creazione di un hash per ogni prodotto, basato sui campi da aggiornare nel database di destinazione: md5 (codice + descrizione + fornitore + circa altri 10 campi). Un nuovo hash basato sugli stessi dati verrà creato su base giornaliera dal database di origine. Conserverò tutti gli hash in una singola tabella (codice articolo, current_hash, old_hash) a scopo di esibizione. Quindi confronta e aggiorna il prodotto se il nuovo hash è diverso da quello vecchio.

Ci sono circa 500.000 prodotti, quindi sono un po 'preoccupato per le prestazioni.

È la buona strada da percorrere?


2
Vogliono che lo faccia anche con gli occhi bendati? Questo è il mio problema in questo momento ...
Captain Hypertext

1
@ Ora, come è andata? Qualche consiglio che puoi offrire ora?
Edwin Evans,

4
@EdwinEvans sostanzialmente sono rimasto con la mia prima idea, ma soprattutto a causa dei vincoli che avevo. Il mio script crea hash md5 in base ai dati chiave per tutti gli elementi. Quindi confronto con gli hash precedenti. Se gli hash sono diversi, carica tutti i dati per l'elemento e aggiorna tutto. Non sono sicuro se questo è il modo migliore, ma funziona di notte e le prestazioni sono decenti.
Neow,

Risposte:


9

Questo è praticamente quello che ho fatto o vissuto negli ultimi anni, e il mio istinto è che il tempo di leggere 500.000 articoli dal database di origine e sincronizzarli nella destinazione non richiederà tutto il tempo che si potrebbe pensare e il il tempo impiegato per leggere i campi "chiave", calcolare l'hash MD5 e il controllo incrociato con la tabella per evitare la sincronizzazione di elementi che non sono cambiati non finirà per risparmiare troppo tempo e potrebbe anche durare più a lungo. Avrei semplicemente letto tutto e aggiornato tutto. Se ciò si traduce in un tempo di esecuzione troppo lungo, comprimerei il tempo di esecuzione rendendo l'ETL muti-threaded, con ogni thread che funziona solo su un segmento della tabella ma funziona in parallelo.

Sarebbe importante assicurarsi che il database di destinazione disponga di un indice chiave primaria o un indice univoco. Altrimenti, ciascuno dei tuoi aggiornamenti / inserti potrebbe bloccare l'intera tabella. Ciò sarebbe negativo se si adotta l'approccio multithread, ma è importante anche se si rimane a thread singolo perché il lavoro potrebbe bloccare la tabella del DB di destinazione e interferire con l'applicazione che si trova su quel DB.

Dici che il DB di origine "potrebbe essere DB2". Quando dici "may" implica che DB è ancora in fase di progettazione / pianificazione? DB2 9 o versioni successive ha il monitoraggio integrato dell'ultimo aggiornamento e la possibilità di eseguire query e recuperare solo gli elementi che sono stati modificati da un determinato momento. Forse è per questo che il DB è stato progettato per non avere una colonna che indica l'ora dell'ultimo aggiornamento, ad esempio:

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

Il limite temporale per la query sopra sarebbe l'ultimo timestamp eseguito dalla sincronizzazione.

In questo caso, ciò dovrebbe risolvere il tuo problema. Tuttavia, la tua soluzione finirà per essere strettamente legata a DB2 e in futuro potrebbe voler passare a un'altra piattaforma DB e aspettarsi che il tuo lavoro di sincronizzazione non debba essere rivisitato. Quindi sarebbe importante assicurarsi che tutte le persone giuste sappiano che il tuo prodotto dipenderà dal rimanere su DB2, o se hanno intenzione di migrare tale migrazione includerebbe la ristrutturazione del DB per avere una colonna "ultimo timestamp" e fare qualunque cosa le modifiche necessarie a livello di app per popolare quel campo.


esiste una soluzione simile anche per mysql?
Fardin Behboudi,

5

La sincronizzazione dei dati sarebbe molto migliore e più veloce, se potesse essere eseguita sulla base di un qualche tipo di identificatore o flag delta. Fondamentalmente, è necessario aggiornare le righe di dati del db di destinazione solo quando non è sincronizzato con il db di origine.

Nel db del server SQL, è possibile utilizzare l'aiuto di Checksum fn anche per creare l'identificatore basato su delta.

È necessario sviluppare un lavoro basato su SQL per essere invocato a una determinata ora del giorno o della notte per ottenere questa logica sql. È meglio eseguirlo come un processo SQL notturno, quando l'utilizzo del database è molto basso. Se il delta dei record db di origine e di destinazione non corrisponde, estrarre solo quei record. Ma il rovescio della medaglia sarebbe calcolare ogni volta il checksum delle righe dei dati di origine e quindi confrontarlo con i dati di destinazione.

Se hai una colonna come "LastModifiedDate" nelle tabelle del db di origine, puoi saltare l'approccio checksum. In questo modo, la valutazione verrà eseguita sulla colonna in base alla data e richiederà meno tempo rispetto all'approccio checksum.


Grazie, ma non sono sicuro che la tua soluzione potrebbe funzionare. Vedi le mie modifiche nella parte "Problemi".
Neow,

Dal momento che non ci sono campi orari aggiornati nel database di origine, non ci resta che estrarre le righe di dati qualificate in base al checksum o all'hash.
Karan,

Dal momento che la tua fonte è db2. Come intendi estrarre i dati da esso? tramite alcuni servizi web o API ..
Karan,

Un dsn è stato creato usando un driver odbc. Posso connettermi e fare query usando pyodbc per Python.
Neow,

Bene, va bene, dato che puoi eseguire le query usando lo strumento chiamato PyODBC nel DB remoto. Puoi fare un'altra cosa. È possibile estrarre i dati del prodotto nello stesso formato in cui si trovano nella nuova "Tabella di gestione temporanea" nel DB di destinazione senza alcun controllo o convalida. In questo modo otterrai i dati in tempo reale in una singola inquadratura nel tuo db target sotto le tabelle dello stage. Successivamente, nel secondo passaggio, è possibile eseguire le operazioni di checksum e aggiornare i dati della tabella transazionale di destinazione. Ciò impedirebbe la valutazione di hash o checksum con i dati db di origine in tempo reale.
Karan,

1

Usare un hash è una buona idea. Dato che la sicurezza non è l'obiettivo in questo caso, scegli una funzione hash che sia veloce (md5 va bene).

A meno che non si preveda di dividere il calcolo dell'hash su più thread / processi, non è necessario archiviare il valore hash corrente nel database. Se il tuo processo è un singolo script, avrai solo l'hash corrente in memoria e lo scriverai nel database come il vecchio hash dopo aver aggiornato i dati nel nuovo database.


-1

dovresti creare un servizio Windows che verrà eseguito in alcuni momenti specifici ogni volta che lo desideri e troverà le modifiche nel database di origine e le inserirà nel database di destinazione.


-1 (in realtà non è stato valutato in senso negativo, ma;) solo per i suggerimenti di Windows. non fare affidamento su alcuna architettura specifica durante lo sviluppo di software significa solo che solo poche persone possono usare le tue cose. l'unica costante è il cambiamento e quindi è meglio non fare affidamento su una piattaforma specifica nella misura in cui le cose sono facili da mantenere per te e per gli utenti
pythonian29033

1
@manish kumar la parte "troverà le modifiche nel database di origine" è la più difficile!
Narvalex,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.