Muszę wdrożyć synchronizację danych między dwiema dużymi bazami danych, które mają zupełnie inne struktury. Zasadniczo muszę wykreślić niektóre dane dotyczące produktów w różnych tabelach w pierwszej bazie danych i ponownie ustawić je dla innych tabel w drugiej bazie danych.
Tworzenie moich produktów po raz pierwszy nie jest bardzo skomplikowane. Ale szukam sposobu na aktualizację niektórych konkretnych danych - nie wszystkich danych - o każdym produkcie.
Oczywiście jest kilka problemów, które sprawiają, że jest to trudne.
- Nie wolno mi nic robić w źródłowej bazie danych oprócz wybierania zapytań.
- W docelowej bazie danych mogę wykonywać zwykłe zapytania (wybierać, aktualizować, wstawiać, tworzyć), ale nie mogę modyfikować istniejącej struktury / tabel.
- Docelowa i źródłowa baza danych mają zupełnie inne struktury, tabele wcale nie są takie same, dlatego dane naprawdę muszą zostać uporządkowane - porównywanie tabel nie będzie działać.
- Docelowa baza danych korzysta z serwera MySQL - źródłem może być DB2.
- Nigdzie nie ma pól „zaktualizowany czas”.
Cały proces musi więc zostać przeprowadzony w jednym (najlepiej) skrypcie w języku Python.
Myślę o stworzeniu skrótu dla każdego produktu na podstawie pól do aktualizacji w docelowej bazie danych: md5 (kod + opis + dostawca + około 10 innych pól). Nowy skrót na podstawie tych samych danych będzie tworzony codziennie ze źródłowej bazy danych. Będę przechowywać wszystkie skróty w jednej tabeli (kod elementu, bieżący skrót, stary skrót) w celu wykonania. Następnie porównaj i zaktualizuj produkt, jeśli nowy skrót różni się od starego.
Istnieje około 500 000 produktów, więc trochę się martwię o występy.
Czy to dobra droga?
Odpowiedzi:
To jest prawie to, co robiłem lub żyję w ciągu ostatnich kilku lat, a mój instynkt podpiera się tym, że czas na odczytanie 500 000 pozycji ze źródłowej bazy danych i synchronizację w miejscu docelowym nie zajmie tyle czasu, ile mogłoby się wydawać, a czas poświęcony na odczytanie pól „klucza”, obliczenie skrótu MD5 i sprawdzenie krzyżowe tabeli, aby uniknąć synchronizacji elementów, które nie uległy zmianie, ostatecznie nie oszczędzają zbyt wiele czasu, a nawet mogą działać dłużej. Po prostu przeczytam wszystko i zaktualizuję wszystko. Jeśli to spowoduje, że środowisko wykonawcze będzie zbyt długie, skompresuję środowisko wykonawcze, tworząc ET-muti z wątkami, przy czym każdy wątek działa tylko na segmencie tabeli, ale działa równolegle.
Ważne jest, aby upewnić się, że docelowa baza danych ma indeks klucza podstawowego lub indeks unikalny. W przeciwnym razie każda z twoich aktualizacji / wstawek może zablokować cały stół. Byłoby to złe, jeśli przyjmujesz podejście wielowątkowe, ale ważne, nawet jeśli pozostajesz jednowątkowy, ponieważ twoje zadanie może zablokować docelową tabelę DB i zakłócać aplikację, która jest na wierzchu tego DB.
Mówisz, że źródłowa baza danych „może być DB2”. Kiedy mówisz „może”, oznacza to, że DB jest nadal projektowane / planowane? Program DB2 9 lub nowszy ma wbudowane śledzenie czasu ostatniej aktualizacji oraz możliwość zapytania i odzyskania tylko elementów, które zmieniły się od czasu. Być może dlatego DB zaprojektowano tak, aby nie zawierała kolumny wskazującej czas ostatniej aktualizacji, np .:
Wartość graniczna znacznika czasu dla powyższego zapytania byłaby ostatnim znacznikiem czasu uruchomionym przez synchronizację.
W takim przypadku powinno to rozwiązać problem. Ale Twoje rozwiązanie byłoby bardzo ściśle powiązane z DB2, aw przyszłości mogą chcieć przejść na inną platformę DB i oczekiwać, że Twoje zadanie synchronizacji nie będzie musiało być ponownie odwiedzane. Dlatego ważne jest, aby upewnić się, że wszystkie właściwe osoby wiedzą, że Twój produkt będzie zależał od pozostania w programie DB2, lub jeśli planują migrację, migracja obejmowałaby restrukturyzację bazy danych, tak aby zawierała kolumnę „ostatnia zmiana znacznika czasu”, i cokolwiek zmiany konieczne na poziomie aplikacji, aby wypełnić to pole.
źródło
Synchronizacja danych byłaby znacznie lepsza i szybsza, gdyby można to zrobić na podstawie pewnego rodzaju identyfikatora delty lub flagi. Zasadniczo należy aktualizować docelowe wiersze danych bazy danych tylko wtedy, gdy nie są zsynchronizowane ze źródłową bazą danych.
W SQL Server db można skorzystać z pomocy sumy kontrolnej fn, aby zbudować identyfikator oparty na delcie.
Powinieneś opracować zadanie oparte na SQL, aby było wywoływane o określonej porze dnia lub nocy, aby uruchomić tę logikę SQL. Lepiej jest uruchomić go jako nocne zadanie SQL, gdy użycie bazy danych jest bardzo niskie. Jeśli delta źródłowego i docelowego rekordu db nie jest zgodna, wyciągnij tylko te rekordy. Minusem byłoby jednak obliczenie sumy kontrolnej wierszy danych źródłowych za każdym razem, a następnie porównanie jej z danymi docelowymi.
Jeśli masz kolumnę typu „LastModifiedDate” w źródłowych tabelach db, możesz pominąć podejście do sumy kontrolnej. W ten sposób ocena zostanie wykonana w kolumnie opartej na dacie i zajmuje mniej czasu w porównaniu do metody sumy kontrolnej.
źródło
Używanie skrótu jest dobrym pomysłem. Ponieważ bezpieczeństwo nie jest celem w tym przypadku, wybierz funkcję skrótu, która jest szybka (md5 jest w porządku).
O ile nie planujesz podzielić obliczeń skrótu na wiele wątków / procesów, tak naprawdę nie musisz przechowywać bieżącej wartości skrótu w bazie danych. Jeśli twój proces jest pojedynczym skryptem, po prostu będziesz mieć bieżący skrót w pamięci i zapisze go w bazie danych jako stary skrót po zaktualizowaniu danych w nowej bazie danych.
źródło
powinieneś utworzyć usługę systemu Windows, która będzie działała w określonych momentach, kiedy tylko zechcesz, a ona znajdzie zmiany w źródłowej bazie danych i wstawi te zmiany do docelowej bazy danych.
źródło