Fazer atualizações no esquema

Com o Spanner, é possível fazer atualizações de esquema sem tempo de inatividade. É possível atualizar o esquema de um banco de dados existente de várias maneiras:

Atualizações de esquema compatíveis

O Spanner é compatível com as seguintes atualizações para o esquema de um banco de dados existente:

  • Adiciona ou remove um esquema nomeado.
  • criar uma nova tabela; As colunas em novas tabelas podem ser NOT NULL.
  • Excluir uma tabela, se nenhuma outra estiver intercalada nela e ela não tiver índices secundários.
  • Crie ou exclua uma tabela com uma chave estrangeira.
  • Adicionar ou remover uma chave externa de uma tabela atual
  • Adicionar uma coluna sem chave a qualquer tabela. As novas colunas sem chave não podem ser NOT NULL.
    • Solte uma coluna sem chave de qualquer tabela, a menos que seja usada por um índice secundário, uma chave externa, uma coluna armazenada ou uma restrição de verificação.
  • Adicione NOT NULL a uma coluna sem chave, excluindo colunas ARRAY.
  • Remova NOT NULL de uma coluna sem chave.
  • Alterar uma coluna STRING para uma coluna BYTES ou uma coluna BYTES para uma coluna STRING.
  • Alterar uma coluna PROTO para uma coluna BYTES ou uma coluna BYTES para uma coluna PROTO.
  • Mude o tipo de mensagem proto de uma coluna PROTO.
  • Adicione novos valores a uma definição de ENUM e renomeie os valores atuais usando ALTER PROTO BUNDLE.
  • Mude as mensagens definidas em um PROTO BUNDLE de maneiras arbitrárias, desde que os campos modificados dessas mensagens não sejam usados como chaves em nenhuma tabela e que os dados atuais atendam às novas restrições.
  • Aumentar ou diminuir o limite de comprimento para um tipo STRING ou BYTES (incluindo para MAX), a menos que seja uma coluna de chave primária herdada por uma ou mais tabelas filho.
  • Aumente ou diminua o limite de comprimento de uma coluna ARRAY<STRING>, ARRAY<BYTES> ou ARRAY<PROTO> até o máximo permitido.
  • Ativar ou desativar carimbos de data/hora de confirmação em colunas de valor e chave principal.
  • Adicione ou remova um índice secundário.
  • Adicionar ou remover uma restrição de verificação de uma tabela existente
  • Adicionar ou remover uma coluna gerada armazenada de uma tabela existente
  • Construa um novo pacote de estatísticas do otimizador.
  • Crie e gerencie visualizações.
  • Criar e gerenciar sequências.
  • Crie papéis de banco de dados e conceda privilégios.
  • Definir, mudar ou remover o valor padrão de uma coluna.
  • Mude as opções do banco de dados (default_leader ou version_retention_period, por exemplo).
  • Criar e gerenciar fluxo de alterações.
  • Criar e gerenciar modelos de ML.

Atualizações de esquema não compatíveis

O Spanner não é compatível com as seguintes atualizações de esquema de um banco de dados existente:

  • Se houver um campo PROTO do tipo ENUM referenciado por uma tabela ou chave de índice, não será possível remover valores ENUM das enumerações proto. A remoção de valores ENUM de enums usados por colunas ENUM<> é compatível, inclusive quando essas colunas são usadas como chaves.

  • Alterar uma coluna STRING(36) para uma coluna UUID ou uma coluna UUID para uma coluna STRING(36).

Desempenho de atualização do esquema

As atualizações de esquema no Spanner não exigem tempo de inatividade. Quando você emite um lote de instruções DDL para um banco de dados do Spanner, pode continuar gravando e lendo nele sem interrupção enquanto o Spanner aplica a atualização como uma operação de longa duração.

O tempo necessário para executar uma instrução de DDL depende de a atualização exigir a validação dos dados existentes ou o preenchimento de dados. Por exemplo, se você adicionar a anotação NOT NULL a uma coluna existente, o Spanner precisará ler todos os valores na coluna para garantir que ela não contenha valores NULL. Essa etapa pode levar muito tempo se houver muitos dados para validar. Outro exemplo é se você estiver adicionando um índice a um banco de dados: o Spanner preenche o índice usando dados existentes, e esse processo pode levar muito tempo, dependendo de como o índice é definido e do tamanho da tabela de base correspondente. No entanto, se você adicionar uma nova coluna a uma tabela, não haverá dados existentes para validar, então o Spanner poderá fazer a atualização em minutos.

Em resumo, as atualizações de esquema que não exigem que o Spanner valide dados existentes podem acontecer em minutos. As atualizações de esquema que necessitam de validação podem demorar mais, dependendo da quantidade de dados existentes que precisam ser validados. Porém, a validação de dados acontece em segundo plano sem afetar o tráfego de produção. As atualizações de esquema que requerem validação de dados são discutidas com mais detalhes na próxima seção.

Atualizações de esquema validadas em relação às definições de visualização

Quando você faz uma atualização de esquema, o Spanner valida que a atualização não vai invalidar as consultas usadas para definir visualizações atuais. Se a validação for bem-sucedida, a atualização do esquema será bem-sucedida. Caso contrário, a atualização do esquema falhará. Consulte Práticas recomendadas ao criar visualizações para mais detalhes.

Atualizações de esquema que exigem validação de dados

É possível fazer atualizações de esquema que exigem a validação de que os dados existentes atendem às novas restrições. Quando uma atualização de esquema exige validação de dados, o Spanner não permite atualizações de esquema conflitantes nas entidades de esquema afetadas e valida os dados em segundo plano. Se a validação for bem-sucedida, a atualização do esquema será bem-sucedida. Caso contrário, a atualização do esquema falhará. As operações de validação são executadas como operações de longa duração. Verifique o status dessas operações para determinar se elas foram bem-sucedidas ou falharam.

Por exemplo, suponha que você tenha definido o seguinte arquivo music.proto com um enum RecordLabel e uma mensagem de protocolo Songwriter:

  enum RecordLabel {
    COOL_MUSIC_INC = 0;
    PACIFIC_ENTERTAINMENT = 1;
    XYZ_RECORDS = 2;
  }

  message Songwriter {
    required string nationality   = 1;
    optional int64  year_of_birth = 2;
  }

Para adicionar uma tabela Songwriters ao seu esquema:

GoogleSQL

CREATE PROTO BUNDLE (
  googlesql.example.music.Songwriter,
  googlesql.example.music.RecordLabel,
);

CREATE TABLE Songwriters (
  Id         INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  Nickname   STRING(MAX),
  OpaqueData BYTES(MAX),
  SongWriter googlesql.example.music.Songwriter
) PRIMARY KEY (Id);

CREATE TABLE Albums (
  SongwriterId     INT64 NOT NULL,
  AlbumId          INT64 NOT NULL,
  AlbumTitle       STRING(MAX),
  Label            INT32
) PRIMARY KEY (SongwriterId, AlbumId);

As seguintes atualizações de esquema são permitidas, mas exigem validação e podem levar mais tempo para serem concluídas, dependendo da quantidade de dados existentes:

  • Adição da anotação NOT NULL a uma coluna sem chave Por exemplo:

    ALTER TABLE Songwriters ALTER COLUMN Nickname STRING(MAX) NOT NULL;
    
  • Redução do comprimento de uma coluna Por exemplo:

    ALTER TABLE Songwriters ALTER COLUMN FirstName STRING(10);
    
  • Alteração de BYTES para STRING Exemplo:

    ALTER TABLE Songwriters ALTER COLUMN OpaqueData STRING(MAX);
    
  • Alteração de INT64/INT32 para ENUM Exemplo:

    ALTER TABLE Albums ALTER COLUMN Label googlesql.example.music.RecordLabel;
    
  • Remoção de valores atuais da definição de enumeração RecordLabel.

  • Ativação de carimbos de data/hora de confirmação em uma coluna TIMESTAMP atual Exemplo:

    ALTER TABLE Albums ALTER COLUMN LastUpdateTime SET OPTIONS (allow_commit_timestamp = true);
    
  • Como adicionar uma restrição de verificação a uma tabela atual.

  • Como adicionar uma coluna armazenada gerada a uma tabela atual.

  • Criação de uma nova tabela com uma chave estrangeira.

  • Como adicionar uma chave externa a uma tabela existente.

Essas atualizações de esquema falharão se os dados subjacentes não satisfizerem as novas restrições. Por exemplo, a instrução ALTER TABLE Songwriters ALTER COLUMN Nickname STRING(MAX) NOT NULL falha se algum valor na coluna Nickname for NULL, porque os dados atuais não atendem à restrição NOT NULL da nova definição.

A validação de dados pode demorar de vários minutos a muitas horas. O tempo para completar a validação de dados depende:

  • O tamanho do conjunto de dados
  • A capacidade de computação da instância
  • da carga na instância.

Algumas atualizações de esquema podem alterar o comportamento das solicitações no banco de dados antes que a atualização do esquema seja concluída. Por exemplo, se você adicionar NOT NULL a uma coluna, o Spanner começará a rejeitar gravações quase imediatamente para novas solicitações que usam NULL para a coluna. Se a nova atualização de esquema acabar falhando na validação de dados, haverá um período de tempo em que as gravações serão bloqueadas, mesmo que elas tenham sido aceitas pelo esquema antigo.

É possível cancelar uma operação de validação de dados de longa duração usando o método projects.instances.databases.operations.cancel ou gcloud spanner operations.

Versões de esquema criadas durante atualizações de esquema

O Spanner usa o controle de versão do esquema para que não haja tempo de inatividade durante uma atualização de esquema para um banco de dados grande. O Spanner mantém a versão antiga do esquema para oferecer suporte a leituras enquanto a atualização do esquema é processada. O Spanner cria uma ou mais novas versões do esquema para processar a atualização. Cada versão contém o resultado de uma coleção de instruções em uma única mudança atômica.

As versões do esquema não correspondem necessariamente um para um com lotes de instruções de DDL ou instruções de DDL individuais. Algumas instruções DDL individuais, como a criação de índices para tabelas base ou instruções existentes que exigem validação de dados, resultam em várias versões de esquema. Em outros casos, várias instruções DDL podem ser agrupadas em uma única versão. As versões de esquema antigas podem consumir recursos significativos de servidor e armazenamento e são retidas até expirarem (não são mais necessárias para disponibilizar leituras de versões anteriores de dados).

A tabela a seguir mostra quanto tempo o Spanner demora para atualizar um esquema.

Operação de esquema Duração estimada
CREATE TABLE Minutos
CREATE INDEX

Minutos para horas, se a tabela base for criada antes do índice.

Minutos, se a instrução for executada ao mesmo tempo que a instrução CREATE TABLE da tabela base.

DROP TABLE Minutos
DROP INDEX Minutos
ALTER TABLE ... ADD COLUMN Minutos
ALTER TABLE ... ALTER COLUMN

Minutos para horas, se a validação de segundo plano for obrigatória.

Minutos, se a validação de segundo plano não for obrigatória.

ALTER TABLE ... DROP COLUMN Minutos
ANALYZE

De alguns minutos a algumas horas, dependendo do tamanho do banco de dados.

Mudanças de tipo de dados e fluxo de alterações

Se você mudar o tipo de dados de uma coluna que um fluxo de mudanças monitora, o campo column_types dos registros de fluxo de mudanças subsequentes relevantes vai refletir o novo tipo, assim como os dados JSON old_values no campo mods dos registros.

O new_values do campo mods de um registro do fluxo de alterações sempre corresponde ao tipo atual de uma coluna. Mudar o tipo de dados de uma coluna monitorada não afeta nenhum registro de fluxo de alterações anterior a essa mudança.

No caso específico de uma mudança de BYTES para STRING, o Spanner valida os valores antigos da coluna como parte da atualização do esquema. Como resultado, o Spanner decodificou com segurança os valores antigos do tipo BYTES em strings quando gravou os registros subsequentes de fluxo de alterações.