Migração de banco de dados: conceitos e princípios (parte 2)

Last reviewed 2024-03-11 UTC

Neste documento, você verá a configuração e a execução do processo de migração do banco de dados, incluindo cenários de falha. Este documento é a última de duas partes. A Parte 1 introduz conceitos, princípios e terminologia de migração de banco de dados com inatividade próxima de zero para arquitetos de nuvem que precisam migrar bancos de dados para o Google Cloud no local ou em outros ambientes de nuvem.

Configuração de migração de banco de dados

Nesta seção, descrevemos as várias fases de uma migração de banco de dados. Primeiro, configure a migração. Em seguida, depois de concluir a migração e alternar os clientes para os bancos de dados de destino, remova os bancos de dados de origem ou, se necessário, implemente um plano substituto devido a problemas com a migração após a migração. Um substituto ajuda a garantir a continuidade dos negócios.

Durante a migração, dê atenção especial a qualquer alteração de esquema ou dados que possa ser introduzida. Para mais informações sobre o impacto dessas alterações, consulte Alterações dinâmicas durante a migração mais adiante neste documento.

Especificação do esquema de destino

Para cada sistema de banco de dados de destino, é necessário definir e criar o esquema. Para migrações de banco de dados homogêneas, você pode criar essa especificação mais rapidamente ao exportar o esquema de banco de dados de origem para o de destino, criando assim o esquema de banco de dados de destino.

O nome do esquema é importante. Uma opção é corresponder os nomes dos esquemas de origem e de destino. No entanto, embora isso simplifique a troca de clientes, essa abordagem pode confundir os usuários se as ferramentas se conectarem aos esquemas de banco de dados de origem e destino simultaneamente, por exemplo, para comparar dados. Se você abstrai o nome do esquema usando um arquivo de configuração, dar nomes diferentes aos esquemas do banco de dados de destino facilita a diferenciação entre eles.

Com as migrações de banco de dados, é necessário criar cada esquema de banco de dados de destino. Esse processo de engenharia pode levar várias iterações. Antes de implementar a migração, talvez seja necessário alterar ainda mais os esquemas para acomodar o processo de migração e as modificações de dados.

Como você provavelmente criará bancos de dados de destino várias vezes ao testar e executar a migração, o processo de criação do esquema precisa ser repetível (o ideal é que seja executado por meio de scripts de instalação). Você pode usar um sistema de gerenciamento de código para controlar a versão dos scripts, garantir consistência e acessar o histórico de alterações dos scripts.

Semântica de execução e migração de consulta

Com o tempo, será necessário migrar os clientes do acesso aos sistemas de banco de dados de origem para os sistemas de banco de dados de destino. Em integrações de banco de dados homogêneas, as consultas podem permanecer inalteradas se os esquemas não forem modificados. Embora os clientes precisem ser testados nos sistemas de banco de dados de destino, eles não precisam ser modificados devido a consultas.

Para migrações de banco de dados, no geral, é necessário modificar as consultas porque os esquemas entre os bancos de dados de origem e de destino são diferentes. A diferença pode ser uma incompatibilidade de tipo de dados entre os bancos de dados de origem e de destino. Além disso, nem todos os recursos da linguagem de consulta disponíveis nos sistemas de banco de dados de origem podem estar disponíveis nos sistemas de banco de dados de destino ou na conversão. Em casos extremos, talvez seja necessário converter uma consulta de um sistema de banco de dados de origem em várias consultas no sistema de destino. Em um cenário inverso, em que você tem mais recursos de linguagem de consulta disponíveis no banco de dados de destino do que na origem, pode ser necessário combinar várias consultas do banco de dados de origem em uma única consulta no banco de dados de destino correspondente.

A semântica das consultas também pode ser diferente. Por exemplo, alguns sistemas de banco de dados materializam uma atualização dentro dessa transação imediatamente. Por isso, quando o mesmo item de dados é lido, o valor atualizado é recuperado. Outros sistemas não materializam uma atualização imediatamente e aguardam a confirmação da transação. Se a lógica no sistema de banco de dados de origem depende da materialização da gravação, a mesma lógica no banco de dados de destino pode causar dados incorretos ou até mesmo falhas.

Se for necessário migrar as consultas, precisará testar todas as funcionalidades para garantir que o comportamento dos clientes seja o mesmo antes e depois da migração. Você também pode testar no nível de dados, mas isso não substitui o teste no nível do cliente. Os clientes executam consultas do ponto de vista da lógica de negócios e só podem ser testados no nível da lógica de negócios.

Processos de migração

Para migrações heterogêneas de banco de dados, os processos de migração especificam como os dados extraídos dos sistemas de banco de dados de origem são modificados e inseridos nos bancos de dados de destino. Modificações de dados, como as discutidas em Alterações de dados neste documento, são definidas e executadas enquanto os itens de dados são extraídos dos bancos de dados de origem e transferidos para os bancos de dados de destino.

Com migrações de banco de dados homogêneas, quando os esquemas dos bancos de dados de origem e de destino são equivalentes, a modificação de dados não é necessária. Os dados são inseridos nos bancos de dados de destino conforme foram extraídos dos bancos de dados de origem.

Dependendo do seu sistema de migração de banco de dados, várias configurações podem ser necessárias. Por exemplo, é necessário especificar se os dados que estão sendo modificados e transferidos precisam ser armazenados intermitentemente no sistema de migração do banco de dados. O armazenamento dos dados pode atrasar o processo geral de migração, mas acelerar significativamente a recuperação se ocorrer uma falha. Talvez seja necessário especificar o tipo de verificação. Por exemplo, alguns sistemas de migração de banco de dados consultam sistemas de origem e de destino para estabelecer a equivalência do conjunto de dados migrado até o ponto da consulta. O tratamento de erros exige que você especifique o comportamento de recuperação de falhas. Novamente, esse requisito depende do sistema de migração de banco de dados em uso.

Lembre-se que você precisa testar sua migração de dados por completo e repetidamente. O ideal é que a migração seja testada para garantir que todos os itens de dados conhecidos sejam migrados, que não ocorram erros de modificação de dados, que o desempenho e a capacidade sejam suficientes e que o tempo de migração possa ser realizado.

Processos substitutos

Durante uma migração de banco de dados, os bancos de dados de origem permanecem operacionais (a menos que a migração envolva a inatividade planejada). Se a migração do banco de dados falhar a qualquer momento, você poderá (no pior dos casos) cancelar a migração e redefinir o banco de dados de destino para o estado inicial. Depois de resolver as falhas, reinicie a migração do banco de dados. A falha e a resolução não afetam os sistemas de banco de dados de origem operacional.

Se ocorrerem falhas depois que a migração do banco de dados for concluída e os clientes forem transferidos para os bancos de dados de destino, o processo de falha e resolução poderá afetar os clientes, de modo que não funcionem corretamente. Na melhor das hipóteses, a falha é resolvida rapidamente e a inatividade para os clientes é curta. No pior dos casos, a falha não é resolvida ou a resolução leva muito tempo, e você precisará alternar os clientes de volta para os bancos de dados de origem.

Para alternar os clientes de volta para os bancos de dados de origem, migre todas as modificações de dados nos bancos de dados de destino para os de origem. É possível configurar e executar esse processo como uma migração de banco de dados completa e separada. No entanto, como os clientes estão inoperantes nos bancos de dados de destino, haverá uma inatividade significativa.

Para evitar a inatividade do cliente nesse cenário, é necessário iniciar os processos de migração imediatamente após a conclusão da migração do banco de dados original. Todas as alterações aplicadas aos sistemas de banco de dados de destino são aplicadas imediatamente aos sistemas de banco de dados de origem. Seguir essa abordagem garante que os sistemas de banco de dados de destino e de origem sejam sempre sincronizados.

Preparar um substituto de bancos de dados de destino para bancos de dados de origem requer um esforço significativo. É fundamental decidir se implementará e testará processos substitutos ou entenderá as consequências de não fazer isso, ou seja, inatividade significativa.

Execução de migração de banco de dados

A execução de uma migração de banco de dados envolve cinco fases distintas, discutidas nesta seção. Uma sexta fase é um substituto, mas um substituto é um caso extremo e considerado uma exceção para uma execução normal de migração de banco de dados.

O processo discutido nesta seção é uma migração de banco de dados de inatividade próxima de zero. Se você conseguir gerar uma inatividade significativa, poderá combinar as três primeiras fases (carregamento inicial, migração contínua e diminuição) em uma fase usando a abordagem de backup/restauração ou exportação/importação.

Uma migração de banco de dados homogênea apresenta um caso especial. Com esse tipo de migração, é possível usar a funcionalidade de replicação do sistema de gerenciamento de banco de dados (para os sistemas compatíveis) que migra os dados enquanto os sistemas de banco de dados de origem permanecem operacionais.

As fases discutidas aqui descrevem uma abordagem que talvez você precise modificar de acordo com os requisitos do processo de migração do banco de dados.

Fase 1: carregamento inicial

O ponto de partida é migrar todos os dados relevantes de todos os bancos de dados de origem. No início da migração de dados, os bancos de dados de origem têm um estado específico, e ele muda durante a migração.

Uma dica para iniciar uma migração enquanto as alterações ocorrem simultaneamente é observar o horário do sistema de banco de dados antes da extração do primeiro item de dados. Com esse carimbo de data/hora, é possível derivar todas as alterações do banco de dados do registro de transações a partir desse momento. Além disso, o carregamento inicial precisa ler um estado de banco de dados consistente em todos os dados. Talvez seja necessário um bloqueio de curta duração no banco de dados para evitar a leitura de um conjunto de dados inconsistente.

Essa fase consiste no seguinte:

  • Anotar o horário do sistema de banco de dados imediatamente antes do início da migração do banco de dados.
  • Executar um processo de migração de carregamento inicial que consulta o conjunto de dados (completo ou parcial) dos bancos de dados de origem que precisam ser migrados e migrar o conjunto de dados. Em um modelo de banco de dados relacional, os processos de migração de carregamento inicial executam consultas como SELECT * ou consultas com seleção, projeção ou ambas. O processo de migração executa a modificação de dados conforme especificado no processo.

Enquanto os processos iniciais de migração de carga são executados, os clientes normalmente fazem alterações nos bancos de dados de origem. Como você registra o horário do sistema de banco de dados no início, pode derivar essas alterações do registro de transações posteriormente.

O resultado da fase de carregamento inicial é a migração completa do conjunto de dados inicial dos sistemas de banco de dados de origem para os sistemas de banco de dados de destino. No entanto, os bancos de dados de origem e de destino ainda não foram sincronizados porque os clientes provavelmente modificaram os bancos de dados de origem durante a migração. A Fase 2 envolve a captura e a migração dessas alterações.

Fase 2: continuação da migração

A migração contínua tem duas finalidades. Primeiro, ele lê as alterações que ocorreram nos bancos de dados de origem após o início do carregamento. Em segundo lugar, ela captura e transfere essas alterações para os bancos de dados de destino.

Essa fase consiste no seguinte:

  • Iniciar os processos de migração contínua a partir do horário do sistema de banco de dados registrado na Fase 1. A migração lê o registro de transações a partir desse momento e aplica todas as alterações ao sistema de banco de dados de destino.
  • Executar qualquer modificação de dados. O processo de migração executa essa etapa conforme você especifica.

Às vezes, as alterações registradas após o horário do sistema do banco de dados são transferidas durante o carregamento inicial. Portanto, é possível que essas alterações possam ser aplicadas uma segunda vez durante a migração contínua. É necessário definir seus processos de migração para garantir que as alterações não sejam aplicadas duas vezes, por exemplo, usando identificadores. Suponha que um item de dados alterado seja transferido durante o carregamento inicial e que essa inserção seja registrada no registro de transações. Ao aplicar um identificador ao item de dados, o sistema de migração pode determinar no registro de transações que outra inserção não é necessária porque o item de dados já existe.

O resultado da fase de migração contínua é que os bancos de dados de destino estão totalmente sincronizados ou quase totalmente sincronizados com os bancos de dados de origem. Quando uma alteração em um sistema de banco de dados de origem não é migrada, você tem um banco de dados quase sincronizado.

Dependendo de como você configura seu sistema de migração de banco de dados, as discrepâncias podem ser pequenas ou grandes. Por exemplo, para aumentar a eficiência, nem todas as alterações precisam ser migradas imediatamente. Caso contrário, você pode criar uma carga intensa na origem se houver alterações no pico de origem. Em geral, as alterações são coletadas e migradas em lotes como operações em massa. Com lotes menores, menos discrepâncias ocorrem entre a origem e o destino, mas sua origem poderá gerar uma carga maior se forem feitas alterações com frequência.

Se o tamanho do lote for configurado dinamicamente, é melhor sincronizar lotes maiores inicialmente na fase de migração contínua e, em seguida, sincronizar lotes de tamanho reduzido gradualmente quando os bancos de dados estiverem quase alcançados. Essa abordagem torna o processo de recuperação mais eficiente e reduz a discrepância entre os bancos de dados de origem e de destino posteriormente.

Fase 3: diminuição

Para se preparar para alternar clientes da origem para os bancos de dados de destino, verifique se os bancos de dados de origem e de destino estão totalmente sincronizados. Drenar é o processo de migração das alterações restantes dos bancos de dados de origem para os bancos de dados de destino.

Essa fase consiste no seguinte:

  • Encerrar os sistemas de banco de dados de origem. Isso significa que nenhuma modificação de dados pode ocorrer no banco de dados de origem e que o registro de transações não recebe entradas de modificação adicionais.
  • Aguardar a migração de todas as alterações para os bancos de dados de destino. Esse processo é a drenagem real das alterações.
  • Após a conclusão da drenagem, faça backup dos bancos de dados de destino para ter um ponto de partida definido para backups incrementais futuros.

O resultado da fase de drenagem é que os sistemas de banco de dados de origem e de destino são sincronizados, e nenhuma modificação de dados ocorrerá.

Para garantir que a drenagem seja concluída, um item de dados de "última inserção" pode ser gravado em um banco de dados de origem. Quando esse item de dados de "última inserção" aparecer no banco de dados de destino correspondente, a fase de drenagem será concluída.

Fase 4: alternância

Após a conclusão da fase de drenagem, é possível alternar os clientes da origem para os bancos de dados de destino. Recomendamos as seguintes práticas recomendadas:

  • Antes de ativar o acesso ao banco de dados de produção, teste a funcionalidade básica para garantir que os clientes estejam operacionais e se comportem conforme o esperado. O número de casos de teste determinará a inatividade real do banco de dados de produção.
  • Faça backup dos bancos de dados de destino antes de ativar o acesso do cliente. Essa prática recomendada garante que o estado inicial dos bancos de dados de destino possa ser recuperado.

No final da transição, os clientes estão totalmente operacionais e começam a acessar bancos de dados de produção (o que este documento denomina bancos de dados de destino até agora).

Fase 5: exclusão do banco de dados de origem

Depois de concluir a transição para os bancos de dados de produção, é possível excluir os bancos de dados de origem. É recomendado fazer um backup final de cada banco de dados de origem para que você tenha um estado final acessível. Os regulamentos de dados também podem exigir backups finais por motivos de conformidade.

Fase 6: substituto

A implementação de um substituto, especialmente para clientes de banco de dados altamente críticos, pode ser uma boa proteção contra problemas e migrações. Um substituto é como uma migração, mas ao contrário. Ou seja, com um substituto, você configura uma migração dos bancos de dados de destino para os bancos de dados de origem. Com as migrações heterogêneas de banco de dados, a substituição é mais complexa. É por isso que recomendamos realizar a transição somente depois de testar minuciosamente se o processo de migração do banco de dados e os aplicativos conectados ao banco de dados de destino cumprem os contratos de nível de serviço (SLAs).

Depois de drenar os bancos de dados de origem e fazer backup de todos os bancos de dados, é possível ativar os processos de migração que identificam as alterações nos bancos de dados de destino e as migram para os bancos de dados de origem antes da transição.

A criação desses processos de migração garante que, depois que os clientes façam alterações nos bancos de dados de destino, os bancos de dados de origem sejam sincronizados e o estado de dados deles seja atualizado. Um substituto pode ser necessário dias ou semanas após a transição. Por exemplo, os clientes podem acessar a funcionalidade pela primeira vez e ser bloqueados devido a funcionalidades que não podem ser corrigidas rapidamente. Nesse caso, os clientes podem voltar a acessar os bancos de dados de origem. Antes que os clientes sejam alternados, todas as alterações nos bancos de dados de destino precisam ser drenadas para os bancos de dados de origem.

Nessa abordagem, algumas circunstâncias exigem atenção especial:

  • É necessário projetar esquemas de destino para que uma migração reversa (de bancos de dados de destino para bancos de dados de origem) seja possível. Por exemplo, se o processo de migração inicial (de origem para destino) tiver junções ou agregações, uma migração reversa não será fácil ou até mesmo impossível. Nesse caso, os dados individuais também precisam estar disponíveis nos bancos de dados de destino.
  • Pode ocorrer um problema em que os bancos de dados de origem têm registros de transações, mas os bancos de dados de destino não fornecem um recurso não funcional. Nesse caso, uma migração reversa (de destino para origem) precisa depender de consultas diferenciais. Essa configuração precisa ser projetada e preparada nos esquemas do banco de dados de destino.
  • Os clientes que operavam originalmente nos bancos de dados de origem precisam estar disponíveis e operacionais para que possam ser ativados em um substituto. Todas as alterações funcionais feitas nos clientes que acessam os bancos de dados de destino também precisam ser feitas nos clientes que acessam o banco de dados de origem para garantir a equivalência funcional.

Embora um substituto seja um último recurso, implementar um substituto é essencial e precisa ser tratado como uma migração de banco de dados completa, que inclui testes.

Alterações dinâmicas durante a migração

Em geral, os bancos de dados são sistemas dinâmicos porque os valores de esquema e dados podem ser alterados. Os esquemas de banco de dados podem mudar com base em fatores como requisitos de negócios, e os valores dos dados podem mudar com ou sem alterações feitas no esquema. Alterações de valores de dados podem acontecer dinamicamente a qualquer momento com as alterações correspondentes da implementação de um aplicativo. As seções a seguir discutem algumas das possíveis alterações e suas implicações para uma migração de banco de dados.

Alterações de esquema

Os bancos de dados podem ser categorizados em sistemas que exigem um esquema predefinido ou que não tenham esquemas. Em geral, os sistemas que exigem um esquema predefinido são compatíveis com operações de alteração de esquema, por exemplo, adicionar atributos ou colunas em um sistema relacional.

Nesses sistemas, você controla as alterações por meio de um processo de gestão da mudança. Um processo de gestão da mudança permite mudanças de maneira controlada. Todas as operações que dependem do esquema, como consultas ou processos de migração de dados, são alteradas simultaneamente para garantir uma alteração geral consistente.

Os sistemas de banco de dados que não exigem um esquema predefinido podem ser alterados a qualquer momento. Uma alteração de esquema não pode ser feita apenas por um usuário autorizado. Em alguns casos, é possível fazer isso de maneira programática. Nesses casos, uma alteração de esquema pode acontecer a qualquer momento. As operações que dependem do esquema podem falhar, como consultas ou processos de migração de dados. Para evitar alterações de esquema não controladas nesses sistemas de banco de dados, é necessário implementar um processo de gerenciamento de mudança como uma convenção e uma regra aceita, e não pela aplicação do sistema.

Alterações de dados

Em geral, os esquemas controlam os possíveis valores de dados para os vários atributos de dados. Os sistemas sem esquema não têm restrições nos valores de dados.

Em ambos os casos, podem aparecer valores de dados que não foram armazenados anteriormente. Por exemplo, os tipos de enumeração geralmente são implementados como um conjunto de strings em sistemas de banco de dados. No nível da linguagem de programação, eles podem ser implementados em clientes como tipos de enumeração verdadeiros, mas não necessariamente. É possível que um cliente armazene o que considera um valor de enumeração válido que outros clientes não consideram válido. Além disso, um processo de migração de dados pode desativar a funcionalidade dos valores de enumeração. Se novos valores aparecerem, o processo de migração de dados poderá falhar.

Outro exemplo é encontrado no armazenamento de estruturas JSON. Em muitos casos, as estruturas JSON são armazenadas em uma string de tipo de dados. No entanto, eles são interpretados como valores JSON no acesso. Se a estrutura JSON mudar, o sistema de banco de dados não detectará isso. Os processos de migração de dados que interpretam uma string como um valor JSON podem falhar.

Alterações no processo de migração

A gestão da mudança durante uma migração contínua do banco de dados é difícil e complexo e pode levar a falhas de migração de dados ou inconsistências. É ideal que as alterações necessárias sejam atrasadas até o final da fase de diminuição, quando os sistemas de banco de dados de origem e de destino serão sincronizados. Nesse momento, as alterações são limitadas aos bancos de dados de destino e aos respectivos clientes (a menos que um substituto também seja implementado).

Se for necessário alterar o processo de migração durante uma migração de dados, recomendamos que mantenha as alterações mínimas e possivelmente faça várias pequenas alterações em vez de uma mais complexa. Além disso, considere primeiro testar essas alterações usando instâncias de teste dos bancos de dados de origem e de destino. O ideal é que você carregue a fonte de teste com dados de produção que serão migrados para o destino de teste. Com essa abordagem, é possível verificar as alterações propostas sem afetar a migração de produção em andamento. Depois de testar e verificar as alterações, você poderá aplicá-las ao seu sistema de produção.

Para que as alterações sejam possíveis durante uma migração de dados em andamento, é necessário interromper o sistema de migração de dados e reiniciá-lo, possivelmente com processos de migração de dados modificados. Nesse caso, não é necessário começar do início com uma fase inicial de carregamento de dados. Se o sistema de migração de dados for compatível com um recurso de execução de migração de teste, você também poderá usá-lo.

Recomendamos que você evite alterar o esquema, os valores ou os processos de migração de dados durante a migração. Se for necessário fazer alterações, reinicie a migração de dados desde o início para garantir que você tenha um estado inicial definido. Em qualquer caso, é fundamental testar usando dados de produção e fazer backup dos bancos de dados antes de aplicar as alterações para que, se necessário, você possa redefinir o sistema geral para um estado consistente.

Mitigação de falhas de migração

Problemas inesperados podem ocorrer durante uma migração de banco de dados. Veja a seguir algumas áreas que podem exigir planejamento prévio:

  • Capacidade insuficiente. Um sistema de migração pode não ter capacidade suficiente, apesar do teste de carga. Esse problema pode ter muitas causas, como um aumento inesperado na taxa de alterações no banco de dados de origem ou na limitação da rede. Para esse caso, prepare recursos adicionais para escalonamento dinâmico ou escalonamento horizontal de todos os componentes envolvidos.
  • Instabilidade do banco de dados. Os bancos de dados de origem ou de destino podem apresentar instabilidade, o que pode atrasar os processos de migração de dados ou impedir o acesso de maneira intermitente. Os processos de migração de dados podem precisar ser recuperados com frequência. Nesse caso, uma alternância intencional de HA ou DR pode resolver o problema. Uma alternância altera o ambiente não funcional (máquinas e armazenamento) e pode ajudar a atenuar o problema. Nesse caso, é necessário testar a alternância e os processos de recuperação da migração do banco de dados para garantir que a alternância não causa inconsistências de dados nos bancos de dados de destino.
  • Exaustão do tamanho do arquivo de registros de transações. Em alguns casos, os registros de transações são armazenados em arquivos que têm um limite máximo. É possível que esse limite seja atingido e a migração do banco de dados falhe. É importante entender quais partes de um sistema de banco de dados podem ser reconfiguradas dinamicamente para lidar com limitações de recursos à medida que surgem. Se alguns aspectos não puderem ser configurados dinamicamente, o dimensionamento inicial precisará ser determinado com cuidado.

Quanto mais realistas forem os testes iniciais, maior será a probabilidade de você encontrar possíveis problemas com antecedência.

A seguir