Práticas recomendadas para alterações de esquema e migração de dados para um banco de dados ativo sem tempo de inatividade?

43

Como você faz alterações de esquema em um banco de dados ativo sem tempo de inatividade?

Por exemplo, digamos que eu tenha um banco de dados PostgreSQL com uma tabela que inclua vários dados do usuário, como endereços de e-mail etc., todos associados a usuários específicos. Se eu quisesse mover os endereços de email para uma nova tabela dedicada, precisaria alterar o esquema e migrar os dados do email para a nova tabela. Como isso pode ser feito sem interromper as gravações na tabela original? Certamente, enquanto os dados são gravados da tabela antiga para a nova, novos dados continuam sendo gravados na tabela antiga e perdidos, certo?

Acho que esse problema surge com bastante frequência, mas não consigo encontrar nenhuma solução padrão para lidar com ele.

Este artigo lida com o problema, mas eu realmente não entendi a etapa 3. Ele diz para gravar nas duas tabelas e migrar os dados antigos da primeira para a nova. Como você garante que está migrando apenas dados antigos?

(Eu uso o PostgreSQL no Heroku .)

Dan Leary
fonte
2
O Facebook desenvolveu uma ferramenta para fazer isso no MySQL.
Nick Chammas
2
K. Scott Allen escreveu sobre um sistema para gerenciar versões de esquema aqui . Criei o DbUpdater, uma ferramenta de código aberto para implantação de esquema com reconhecimento de versão. Mais aqui - http://www.tewari.info/dbupdater
ash
@NickChammas Obrigado por compartilhar isso. Eu tenho muitas perguntas sobre isso. Você poderia sugerir um tutorial mais detalhado, um vídeo, de preferência, que explica coisas como registro de bits, índices não clusterizados e responde a perguntas como: 1. Como a seleção de dados da tabela de origem em um arquivo externo reduz a carga em comparação com a cópia para o destino tabela diretamente. 2. Quando a fase de cópia terminará? Estas são apenas algumas perguntas que tenho e só comecei a lê-lo.
Sandeepan Nath
@SandeepanNath - Desculpe, eu não estou tão familiarizado com a ferramenta do Facebook e, portanto, não posso apontar mais recursos. Li um anúncio sobre isso e postei meu comentário anos atrás, mas nunca o usei.
Nick Chammas

Respostas:

27

Você quase já tem sua resposta:

  1. Crie a nova estrutura em paralelo
  2. Comece a escrever nas duas estruturas
  3. Migrar dados antigos para a nova estrutura
  4. Escreva e leia apenas nova estrutura
  5. Excluir colunas antigas

Quanto à etapa 3 , use algo como isto (em uma transação):

Insira o que ainda não existe:

INSERT INTO new_tbl (old_id, data)
SELECT old_id, data
FROM   old_tbl
WHERE  NOT EXISTS (SELECT * FROM new_tbl WHERE new_tbl.old_id = old_tbl.old_id);

Atualize o que mudou nesse meio tempo:

UPDATE new_tbl
SET    data  = old.data
USING  old_tbl
WHERE  new_tbl.old_id = old_tbl.old_id
AND    new_tbl.data IS DISTINCT FROM old_tbl.data;

Novos dados não serão tocados, porque são idênticos nos dois lugares.

Erwin Brandstetter
fonte
Tenho algumas perguntas ao tentar entender o cenário para o qual você propôs esta resposta: 1. As alterações de código serão implantadas junto com o início das alterações de banco de dados? 2. Por que será necessário escrever para as duas estruturas? 3. Por que a nova estrutura não pode ser apresentada primeiro e, em seguida, os dados existentes podem ser migrados e, em seguida, implementadas as alterações de código que preencherão a nova estrutura? 4. Por que é necessário descobrir o que não existe (sua primeira consulta)? Você está propondo a inserção em várias tentativas?
Sandeepan Nath
2
@SandeepanNath, para responder à pergunta 3 em seu comentário: porque se você (a) criar uma nova estrutura, (b) migrar dados para ela, (c) alterar seu código para gravar dados na nova estrutura em vez da antiga, então todos as alterações de dados feitas entre as etapas be c somente existirão na estrutura antiga . A questão era como fazer alterações no esquema sem tempo de inatividade. Leia esta resposta novamente, com cuidado.
Curinga