Melhor maneira de sincronizar dados entre dois bancos de dados diferentes

24

Eu tenho que implementar a sincronização de dados entre dois grandes bancos de dados que possuem estruturas completamente diferentes. Basicamente, preciso extrair alguns dados sobre produtos em tabelas diferentes no primeiro banco de dados e reorganizá-los para outras tabelas no segundo banco de dados.

Criar meus produtos pela primeira vez não é muito complicado. Mas estou procurando uma maneira de atualizar alguns dados específicos - nem todos os dados - sobre cada produto.

Obviamente, existem alguns problemas que tornam isso complicado.

  • Não estou autorizado a fazer nada no banco de dados de origem além das consultas selecionadas.
  • No banco de dados de destino, eu posso fazer consultas comuns (selecionar, atualizar, inserir, criar), mas não consigo modificar a estrutura / tabelas existentes.
  • O banco de dados de destino e de origem tem estruturas completamente diferentes, as tabelas não são as mesmas, portanto os dados realmente precisam ser reorganizados - a comparação de tabelas não funciona.
  • O banco de dados de destino usa um servidor MySQL - a origem pode ser o DB2.
  • Não há campos de "horário atualizado" em lugar nenhum.

Portanto, todo o processo precisa ser feito em um único script Python (idealmente).

Penso em criar um hash para cada produto, com base nos campos a serem atualizados no banco de dados de destino: md5 (código + descrição + fornecedor + cerca de 10 outros campos). Um novo hash com base nos mesmos dados será criado diariamente a partir do banco de dados de origem. Armazenarei todos os hashes em uma única tabela (código do item, current_hash, old_hash) para fins de desempenho. Em seguida, compare e atualize o produto se o novo hash for diferente do antigo.

Existem cerca de 500 000 produtos, por isso estou um pouco preocupado com o desempenho.

É o bom caminho a percorrer?

Neow
fonte
2
Eles querem que você faça isso com os olhos vendados também? Esse é o meu problema agora ...
Capitão Hypertext
1
@ Agora, como foi? Algum conselho que você pode oferecer agora?
Edwin Evans
4
@ EdwinEvans basicamente fiquei com minha primeira ideia, mas principalmente devido a restrições que eu tinha. Meu script cria hashes MD5 com base nos dados principais de todos os itens. Então eu comparo com hashes anteriores. Se os hashes forem diferentes, ele carregará todos os dados do item e atualizará tudo. Não tenho certeza se esse é o melhor caminho, mas é executado à noite e as performances são decentes.
Neow 22/05/19

Respostas:

9

Isso é basicamente o que tenho feito ou vivido nos últimos anos, e meu instinto é que o tempo para ler 500.000 itens do banco de dados de origem e sincronizar no destino não levará tanto tempo quanto se pode pensar. O tempo necessário para ler os campos "chave", calcular o hash MD5 e verificar com sua tabela para evitar a sincronização de itens que não foram alterados não economizarão muito tempo e podem demorar mais. Eu simplesmente leria tudo e atualizaria tudo. Se isso resultar em um tempo de execução muito longo, compactaria o tempo de execução, tornando o ETL com thread muti, com cada thread operando apenas em um segmento da tabela, mas trabalhando em paralelo.

Seria importante garantir que seu banco de dados de destino tenha um índice de chave primária ou índice exclusivo. Caso contrário, cada uma de suas atualizações / inserções poderá bloquear a tabela inteira. Isso seria ruim se você adotasse a abordagem multithread, mas importante mesmo se você permanecer com um thread único porque seu trabalho poderia bloquear a tabela do banco de dados de destino e interferir no aplicativo montado sobre esse banco de dados.

Você diz que o banco de dados de origem "pode ​​ser o DB2". Quando você diz "pode", isso implica que o banco de dados ainda está sendo projetado / planejado? O DB2 9 ou superior possui rastreamento integrado do horário da última atualização e a capacidade de consultar e recuperar apenas os itens que foram alterados desde um ponto no tempo. Talvez seja por isso que o banco de dados foi projetado para não ter uma coluna indicando a última hora atualizada, por exemplo:

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

O limite de carimbo de data e hora da consulta acima seria o último carimbo de data e hora executado pela sincronização.

Se for esse o caso, isso deve resolver o seu problema. Porém, sua solução acabaria atrelada muito fortemente ao DB2 e, no futuro, eles poderão mudar para outra plataforma de banco de dados e esperar que seu trabalho de sincronização não precise ser re-visitado. Portanto, seria importante garantir que todas as pessoas certas saibam que seu produto dependerá da permanência no DB2, ou se planejam migrar essa migração incluiria a reestruturação do banco de dados para ter uma coluna "última alteração de data e hora" e fazer o que quer alterações necessárias no nível do aplicativo para preencher esse campo.

Thomas Carlisle
fonte
Existe alguma solução semelhante para o mysql também?
Fardin Behboudi
5

A sincronização de dados seria muito melhor e mais rápida, se puder ser feita com base em algum tipo de identificador ou sinalizador delta. Basicamente, você deve atualizar as linhas de dados do banco de dados de destino apenas quando estiver fora de sincronia com o banco de dados de origem.

No SQL server db, você pode ter a ajuda da soma de verificação fn também para criar o identificador baseado em delta.

Você deve desenvolver um trabalho baseado em SQL para ser chamado em um determinado horário do dia ou da noite para ativar essa lógica sql. É melhor executá-lo como um trabalho SQL noturno, quando o uso do banco de dados é muito baixo. Se o delta dos registros de origem e de destino db não corresponder, puxe apenas esses registros. Mas a desvantagem seria calcular a soma de verificação das linhas de dados de origem toda vez e depois compará-la com os dados de destino.

Se você tiver uma coluna como "LastModifiedDate" nas tabelas de banco de dados de origem, poderá ignorar a abordagem de soma de verificação. Dessa forma, sua avaliação será executada na coluna com base em data e levará menos tempo em comparação com a abordagem de soma de verificação.

Karan
fonte
Obrigado, mas não tenho certeza de que sua solução funcione - veja minhas edições na parte "problemas".
Neow
Como não há campos de tempo atualizados no banco de dados de origem, resta extrair as linhas de dados qualificadas com base na soma de verificação ou no hash.
Karan
Como sua fonte é db2. Como você pretende extrair os dados? através de algum webservice ou API ..
Karan
Um dsn foi configurado usando um driver odbc. Posso conectar e fazer consultas usando pyodbc para Python.
Neow
Tudo bem, isso é bom, pois você pode executar as consultas usando a ferramenta chamada PyODBC no banco de dados remoto. Você pode fazer mais uma coisa. Você pode extrair os dados do produto diretamente no mesmo formato da nova tabela de preparação no banco de dados de destino sem nenhuma verificação ou validação. Dessa forma, você obterá os dados ao vivo em um único tiro no banco de dados alvo, sob as tabelas de palco. Posteriormente, na segunda etapa, você poderá executar as operações de soma de verificação e atualizar os dados da tabela transacional de destino. Isso impediria a avaliação do hash ou da soma de verificação com os dados do banco de dados de origem em tempo real.
Karan
1

Usar um hash é uma boa ideia. Como a segurança não é o objetivo nesse caso, escolha uma função de hash que seja rápida (md5 está correto).

A menos que você planeje dividir o cálculo do hash em vários encadeamentos / processos, você realmente não precisa armazenar o valor atual do hash no banco de dados. Se o seu processo for um script único, você terá apenas o hash atual na memória e o gravará no banco de dados como o hash antigo depois de atualizar os dados no novo banco de dados.

Kent A.
fonte
-1

você deve criar um serviço do Windows que será executado em alguns momentos específicos sempre que desejar e ele encontrará as alterações no banco de dados de origem e as inserirá no banco de dados de destino.

manish kumar
fonte
-1 (realmente não diminuiu o voto, mas;) apenas para sugestões do Windows. não vamos confiar em nenhuma arquitetura específica ao desenvolver software, apenas significa que apenas algumas pessoas podem usar suas coisas. a única constante é a mudança e por isso é melhor não confiar em qualquer plataforma específica na medida em que torna as coisas fáceis de manter para si mesmo e para os usuários
pythonian29033
1
@manish kumar a parte "ela encontrará as alterações no seu banco de dados de origem" é a mais difícil!
Narvalex 25/08/19