Meilleure façon de synchroniser les données entre deux bases de données différentes


24

Je dois implémenter la synchronisation des données entre deux grandes bases de données qui ont des structures complètement différentes. Fondamentalement, j'ai besoin de saisir des données sur les produits dans différentes tables de la première base de données et de les réorganiser pour d'autres tables dans la deuxième base de données.

Créer mes produits du premier coup n'est pas très compliqué. Mais je cherche un moyen de mettre à jour certaines données spécifiques - pas toutes les données - sur chaque produit.

De toute évidence, il y a quelques problèmes qui rendent cela délicat.

  • Je ne suis pas autorisé à faire quoi que ce soit sur la base de données source, à l'exception des requêtes sélectionnées.
  • Sur la base de données cible, je peux faire des requêtes habituelles (sélectionner, mettre à jour, insérer, créer) mais je ne peux pas modifier la structure / les tables existantes.
  • Les bases de données cible et source ont des structures complètement différentes, les tables ne sont pas du tout les mêmes, donc les données doivent vraiment être réorganisées - la comparaison des tables ne fonctionnera pas.
  • La base de données cible utilise un serveur MySQL - la source peut être DB2.
  • Il n'y a aucun champ "heure de mise à jour" nulle part.

Donc, tout le processus doit être fait dans un seul script Python (idéalement).

Je pense à créer un hachage pour chaque produit, en fonction des champs à mettre à jour dans la base de données cible: md5 (code + description + fournisseur + environ 10 autres champs). Un nouveau hachage basé sur les mêmes données sera créé quotidiennement à partir de la base de données source. Je vais stocker tous les hachages dans une seule table (code d'article, current_hash, old_hash) à des fins de performances. Comparez puis mettez à jour le produit si le nouveau hachage est différent de l'ancien.

Il y a environ 500 000 produits donc je suis un peu inquiet pour les performances.

Est-ce la bonne voie à suivre?


2
Veulent-ils que vous le fassiez les yeux bandés aussi? C'est mon problème en ce moment ...
Captain Hypertext

1
@Now, comment ça s'est passé? Un conseil que tu peux offrir maintenant?
Edwin Evans

4
@EdwinEvans, je suis resté avec ma première idée, mais surtout en raison des contraintes que j'avais. Mon script crée des hachages md5 en fonction des données clés pour tous les éléments. Ensuite, je compare avec les hachages précédents. Si les hachages sont différents, il charge toutes les données de l'élément et met à jour tout. Je ne sais pas si c'est le meilleur moyen, mais il fonctionne la nuit et les performances sont correctes.
Neow

Réponses:


9

C'est à peu près ce que j'ai fait ou vécu ces dernières années, et mon instinct est que le temps de lire 500 000 éléments de la base de données source et de se synchroniser dans la destination ne prendra pas autant de temps qu'on pourrait le penser et le temps nécessaire pour lire les champs "clé", calculer le hachage MD5 et recouper avec votre table pour éviter de synchroniser les éléments qui n'ont pas changé ne finira pas par gagner trop de temps et peut même s'exécuter plus longtemps. Je voudrais simplement tout lire et tout mettre à jour. Si cela se traduit par un temps d'exécution trop long, je compresserais le temps d'exécution en rendant l'ETL multi-thread, chaque thread fonctionnant uniquement sur un segment de la table mais travaillant en parallèle.

Il serait important de vous assurer que votre base de données de destination possède un index de clé primaire ou un index unique. Sinon, chacune de vos mises à jour / insertions pourrait verrouiller la table entière. Ce serait mauvais si vous adoptez l'approche multithread, mais important même si vous restez monothread parce que votre travail pourrait verrouiller la table de base de données de destination et interférer avec l'application qui chevauche cette base de données.

Vous dites que la DB source "peut être DB2". Lorsque vous dites «peut», cela signifie que la base de données est toujours en cours de conception / planification? DB2 9 ou supérieur dispose d'un suivi intégré de l'heure de la dernière mise à jour et de la possibilité d'interroger et de récupérer uniquement les éléments qui ont changé depuis un certain temps. C'est peut-être la raison pour laquelle la base de données a été conçue pour ne pas avoir de colonne indiquant la dernière heure mise à jour, par exemple:

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

La coupure d'horodatage pour la requête ci-dessus serait le dernier horodatage exécuté par votre synchronisation.

Si tel est le cas, cela devrait résoudre votre problème. Mais, votre solution finirait par être très étroitement liée à DB2 et à l'avenir, ils pourraient souhaiter passer à une autre plate-forme DB et s'attendre à ce que votre travail de synchronisation n'ait pas besoin d'être revu. Il serait donc important de vous assurer que toutes les bonnes personnes savent que votre produit dépendra de son maintien sur DB2, ou si elles prévoient de migrer, cette migration inclurait la restructuration de la base de données pour avoir une colonne "horodatage modifié en dernier" et faire tout les modifications nécessaires au niveau de l'application pour remplir ce champ.


existe-t-il une solution similaire pour mysql aussi?
Fardin Behboudi

5

La synchronisation des données serait bien meilleure et plus rapide, si elle pouvait se faire sur la base d'un identifiant delta ou d'un indicateur. Fondamentalement, vous devez mettre à jour les lignes de données de la base de données cible uniquement lorsqu'elles ne sont pas synchronisées avec la base de données source.

Dans la base de données SQL Server, vous pouvez également utiliser l'aide de la somme de contrôle fn pour créer l'identificateur basé sur delta.

Vous devez développer un travail basé sur SQL pour être invoqué à une certaine heure du jour ou de la nuit afin de déclencher cette logique SQL. Il est préférable de l'exécuter en tant que tâche SQL nocturne, lorsque l'utilisation de la base de données est très faible. Si le delta des enregistrements source et cible ne correspond pas, extrayez uniquement ces enregistrements. Mais l'inconvénient serait de calculer la somme de contrôle des lignes de données source à chaque fois, puis de la comparer avec les données cibles.

Si vous avez une colonne comme "LastModifiedDate" dans les tables de base de données source, vous pouvez ignorer l'approche de la somme de contrôle. De cette façon, votre évaluation sera exécutée sur la colonne basée sur la date et prend moins de temps par rapport à l'approche de la somme de contrôle.


Merci mais je ne suis pas sûr que votre solution puisse fonctionner - voir mes modifications dans la partie "problèmes".
Neow

Puisqu'il n'y a pas de champs d'heure mis à jour dans la base de données source, il nous reste à extraire les lignes de données qualifiées en fonction de la somme de contrôle ou du hachage.
Karan

Puisque votre source est db2. Comment comptez-vous en extraire les données? via un webservice ou une API ..
Karan

Un DSN a été configuré à l'aide d'un pilote ODBC. Je peux me connecter et faire des requêtes en utilisant pyodbc pour Python.
Neow

C'est bien, car vous pouvez effectuer les requêtes à l'aide de l'outil appelé PyODBC dans la base de données distante. Vous pouvez faire encore une chose. Vous pouvez extraire les données produit directement dans le même format que dans la nouvelle "table de transfert" de votre base de données cible sans aucun contrôle ni validation. De cette façon, vous obtiendrez les données en direct en un seul coup dans votre base de données cible sous les tables de scène. Plus tard dans la deuxième étape, vous pouvez effectuer les opérations de somme de contrôle et mettre à jour les données de table transactionnelle cible. Cela empêcherait le hachage ou l'évaluation de la somme de contrôle avec les données de base de données en temps réel.
Karan

1

L'utilisation d'un hachage est une bonne idée. Puisque la sécurité n'est pas l'objectif dans ce cas, choisissez une fonction de hachage rapide (md5 est très bien).

Sauf si vous prévoyez de diviser le calcul du hachage sur plusieurs threads / processus, vous n'avez pas vraiment besoin de stocker la valeur de hachage actuelle dans la base de données. Si votre processus est un script unique, vous n'aurez que le hachage actuel en mémoire et l'écrirez dans la base de données comme l'ancien hachage après avoir mis à jour les données dans la nouvelle base de données.


-1

vous devez avoir créé un service Windows qui s'exécutera à certains moments précis à tout moment et il trouvera les modifications dans votre base de données source et insérera ces modifications dans votre base de données de destination.


-1 (pas vraiment de downvote, mais;) pour la suggestion Windows uniquement. ne nous appuyons pas sur une architecture spécifique lors du développement de logiciels, cela signifie simplement que seules quelques personnes peuvent utiliser vos trucs. la seule constante est le changement et il est donc préférable de ne pas s'appuyer sur une plateforme spécifique dans la mesure où cela facilite la maintenance pour vous-même et pour les utilisateurs
pythonian29033

1
@manish kumar la partie "il trouvera les changements dans votre base de données source" est la plus difficile!
Narvalex
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.