Esta página descreve como migrar chaves primárias das tabelas do banco de dados de origem para bancos de dados de dialetos do GoogleSQL e do PostgreSQL no Spanner. Antes de executar os procedimentos na página, consulte a Visão geral da migração de chaves primárias.
Antes de começar
-
Para receber as permissões necessárias para migrar chaves primárias para o Spanner, peça ao administrador para conceder a você o papel do IAM de Administrador do banco de dados do Cloud Spanner (
roles/spanner.databaseAdmin
) na instância.
Migrar chaves sequenciais geradas automaticamente
Se você estiver migrando de um banco de dados que usa chaves monotônicas sequenciais, como
AUTO_INCREMENT
no MySQL, SERIAL
no PostgreSQL ou o tipo IDENTITY
padrão no SQL Server ou
Oracle, considere a seguinte estratégia de migração de alto nível:
- No Spanner, replique a estrutura da tabela do seu banco de dados de origem usando uma chave primária inteira.
- Para cada coluna no Spanner que contém valores sequenciais,
crie uma sequência e atribua a função
GET_NEXT_SEQUENCE_VALUE
( GoogleSQL, PostgreSQL) como o valor padrão da coluna. - Migre os dados atuais com chaves originais do banco de dados de origem para o
Spanner. Use a ferramenta de migração
do Spanner ou um
modelo do
Dataflow.
- Opcionalmente, é possível estabelecer restrições de chave estrangeira para qualquer tabela dependente.
- Antes de inserir novos dados, ajuste a sequência do Spanner para pular o intervalo de valores de chave existentes.
- Inserir novos dados, permitindo que a sequência gere chaves exclusivas automaticamente.
Exemplo de fluxo de trabalho de migração
O código abaixo define a estrutura da tabela e a sequência relacionada no
Spanner usando um objeto SEQUENCE
e define o objeto como o valor principal padrão da tabela
de destino:
GoogleSQL
CREATE SEQUENCE singer_id_sequence OPTIONS ( SequenceKind = 'bit_reversed_positive' ); CREATE TABLE Singers ( SingerId INT64 DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE SingerIdSequence)), Name STRING(1024), Biography STRING(MAX), ) PRIMARY KEY (SingerId); CREATE TABLE Albums ( AlbumId INT64, SingerId INT64, AlbumName STRING(1024), SongList STRING(MAX), CONSTRAINT FK_singer_album FOREIGN KEY (SingerId) REFERENCES Singers (SingerId) ) PRIMARY KEY (AlbumId);
PostgreSQL
CREATE SEQUENCE SingerIdSequence BIT_REVERSED_POSITIVE; CREATE TABLE Singers ( SingerId BIGINT DEFAULT nextval('SingerIdSequence') PRIMARY KEY, Name VARCHAR(1024) NOT NULL, Biography TEXT ); CREATE TABLE Albums ( AlbumId BIGINT PRIMARY KEY, SingerId BIGINT, AlbumName VARCHAR(1024), SongList TEXT, CONSTRAINT FK_singer_album FOREIGN KEY (SingerId) REFERENCES Singers (SingerId) );
A opção bit_reversed_positive
indica que os valores gerados pela
sequência são do tipo INT64
, são maiores que zero e não são sequenciais.
À medida que você migra as linhas atuais do seu banco de dados de origem para o Spanner, as chaves primárias não são alteradas.
Para novas inserções que não especificam uma chave primária, o Spanner
recupera automaticamente um novo valor chamando a função
GET_NEXT_SEQUENCE_VALUE
(GoogleSQL
ou PostgreSQL).
Esses valores são distribuídos uniformemente no intervalo
[1, 263]
, e podem ocorrer colisões com as
chaves atuais. Para evitar isso, configure a sequência usando ALTER_SEQUENCE
(GoogleSQL
ou PostgreSQL)
para pular o intervalo de valores coberto pelas chaves atuais.
Suponha que a tabela singers
foi migrada do PostgreSQL, em que a chave primária singer_id
é do tipo SERIAL
. O PostgreSQL a seguir
mostra o DDL do banco de dados de origem:
PostgreSQL
CREATE TABLE Singers ( SingerId SERIAL PRIMARY KEY, Name varchar(1024), Biography varchar );
Os valores da chave primária estão aumentando de forma monotonicamente. Após a migração, você
pode recuperar o valor máximo da chave primária singer_id
no
Spanner. Use o seguinte código no Spanner:
GoogleSQL
SELECT MAX(SingerId) FROM Singers;
PostgreSQL
SELECT MAX(SingerId) FROM Singers;
Suponha que o valor retornado seja 20.000. É possível configurar a
sequência Spanner para pular o intervalo [1, 21000]
. Os outros
1.000 servem como um buffer para acomodar gravações no banco de dados de origem após a
migração inicial. As novas chaves geradas no Spanner não entram em conflito
com o intervalo de chaves primárias geradas no banco de dados PostgreSQL
de origem. Use o seguinte código no Spanner:
GoogleSQL
ALTER SEQUENCE SingerIdSequence SET OPTIONS ( skip_range_min = 1, skip_range_max = 21000 );
PostgreSQL
ALTER SEQUENCE SingerIdSequence SKIP RANGE 1 21000;
Usar o Spanner e o banco de dados de origem
É possível usar o conceito de intervalo de omissão para oferecer suporte a cenários em que o Spanner ou o banco de dados de origem geram chaves primárias, por exemplo, para ativar a replicação em qualquer direção para recuperação de desastres durante uma transição de migração.
Para isso, os dois bancos de dados geram chaves primárias, e os dados são sincronizados entre eles. É possível configurar cada banco de dados para criar chaves primárias em intervalos de chaves não sobrepostos. Ao definir um intervalo para o banco de dados de origem, você pode configurar a sequência do Spanner para pular esse intervalo.
Por exemplo, após a migração do aplicativo de faixas de música, replique os dados do PostgreSQL para o Spanner para reduzir o tempo necessário para a transição.
Depois de atualizar e testar o aplicativo no Spanner, você pode parar de usar o banco de dados PostgreSQL de origem e usar o Spanner, tornando-o o sistema de registro para atualizações e novas chaves primárias. Quando o Spanner assume o controle, é possível reverter o fluxo de dados entre os bancos de dados para a instância do PostgreSQL.
Suponha que o banco de dados PostgreSQL de origem use chaves primárias SERIAL
,
que são números inteiros assinados de 32 bits. As chaves primárias do Spanner são
números maiores de 64 bits. No PostgreSQL, mude a coluna da chave primária para
ser uma coluna de 64 bits ou bigint
. Use o código abaixo no banco de dados
PostgreSQL de origem:
PostgreSQL
ALTER TABLE Singers ALTER COLUMN SingerId TYPE bigint;
É possível definir uma restrição CHECK
para a tabela no banco de dados PostgreSQL de origem
para garantir que os valores da chave primária SingerId
sejam sempre menores
ou iguais a 231-1
.
Use o seguinte código no seu banco de dados PostgreSQL de origem:
PostgreSQL
ALTER TABLE Singers ADD CHECK (SingerId <= 2147483647);
No Spanner, podemos alterar a sequência para pular o
intervalo [1, 231-1]
.
Use o seguinte código no Spanner:
GoogleSQL
ALTER SEQUENCE SingerIdSequence SET OPTIONS (
skip_range_min = 1,
skip_range_max = 2147483647 -- 231-1
);
PostgreSQL
ALTER SEQUENCE SingerIdSequence SKIP RANGE 1 2147483648;
O banco de dados PostgreSQL de origem sempre gera chaves no espaço de números inteiros de 32 bits, enquanto as chaves do Spanner são restritas ao espaço de números inteiros de 64 bits, maior do que todos os valores de números inteiros de 32 bits. Isso garante que os bancos de dados possam gerar chaves primárias de forma independente sem conflitos.
Migrar colunas de chave UUID
As chaves UUIDv4 são únicas, independentemente de onde são geradas. As chaves UUID geradas em outro lugar são integradas a novas chaves UUID geradas no Spanner.
Considere a seguinte estratégia de alto nível para migrar chaves UUID para o Spanner:
- Defina as chaves UUID no Spanner usando colunas de string com uma
expressão padrão. Use a função
GENERATE_UUID()
(GoogleSQL, PostgreSQL). - Exporte os dados do sistema de origem, serializando as chaves UUID como strings.
- Importe as chaves primárias para o Spanner.
- Opcional: ative as chaves estrangeiras.
Confira um exemplo de fluxo de trabalho de migração:
No Spanner, defina uma coluna de chave primária UUID como um tipo STRING
ou
TEXT
e atribua GENERATE_UUID()
(GoogleSQL
ou
PostgreSQL)
como o valor padrão. Migre todos os dados do seu banco de dados de origem para o
Spanner. Após a migração, conforme novas linhas são inseridas,
o Spanner chama GENERATE_UUID()
para gerar novos valores de UUID para
as chaves primárias. Por exemplo, a chave primária FanClubId
recebe um valor UUIDv4
quando uma nova linha é inserida na tabela FanClubs
. Use o seguinte código no
Spanner:
GoogleSQL
CREATE TABLE Fanclubs ( FanClubId STRING(36) DEFAULT (GENERATE_UUID()), ClubName STRING(1024), ) PRIMARY KEY (FanClubId); INSERT INTO FanClubs (ClubName) VALUES ("SwiftFanClub");
PostgreSQL
CREATE TABLE FanClubs ( FanClubId TEXT DEFAULT spanner.generate_uuid() PRIMARY KEY, ClubName VARCHAR(1024) ); INSERT INTO FanClubs (ClubName) VALUES ('SwiftFanClub');
Migrar suas próprias chaves primárias
O aplicativo pode depender da ordem da chave primária para determinar a relevância dos dados ou para ordenar os dados recém-criados. Para usar chaves sequenciais geradas externamente no Spanner, crie uma chave composta que combine um valor distribuído uniformemente, como um hash, como o primeiro componente e a chave sequencial como o segundo componente. Dessa forma, é possível preservar os valores de chave sequenciais sem criar pontos de acesso em grande escala. Considere o seguinte fluxo de trabalho de migração:
Suponha que você precise migrar uma tabela do MySQL students
com uma chave primária
AUTO_INCREMENT
para o Spanner. Use o seguinte código no seu banco de dados
MySQL de origem:
MySQL
CREATE TABLE Students ( StudentId INT NOT NULL AUTO_INCREMENT, Info VARCHAR(2048), PRIMARY KEY (StudentId) );
No Spanner, é possível adicionar uma coluna gerada StudentIdHash
criando um hash da coluna StudentId
. Exemplo:
StudentIdHash = FARM_FINGERPRINT(CAST(StudentId AS STRING))
Use o seguinte código no Spanner:
GoogleSQL
CREATE TABLE student ( StudentIdHash INT64 AS (FARM_FINGERPRINT(cast(StudentId as string))) STORED, StudentId INT64 NOT NULL, Info STRING(2048), ) PRIMARY KEY(StudentIdHash, StudentId);
PostgreSQL
CREATE TABLE Student ( StudentIdHash bigint GENERATED ALWAYS AS (FARM_FINGERPRINT(cast(StudentId AS varchar))) STORED, StudentId bigint NOT NULL, Info varchar(2048), PRIMARY KEY (StudentIdHash, StudentId) );
Migrar colunas de chave sequencial
Se o sistema de banco de dados de origem gerar valores sequenciais para uma coluna de chave, use uma sequência positiva invertida (GoogleSQL, PostgreSQL) no esquema do Spanner para gerar valores que sejam distribuídos uniformemente no espaço de número inteiro positivo de 64 bits. Para evitar que a sequência do Spanner gere um valor que se sobrepõe a um valor migrado, defina um intervalo ignorado para ela.
Por exemplo, você pode pular o intervalo de 1 a 4.294.967.296 (2^32) para as duas sequências a seguir, se souber que o banco de dados de origem gera apenas números inteiros de 32 bits:
GoogleSQL
CREATE SEQUENCE MyFirstSequence OPTIONS ( sequence_kind = "bit_reversed_positive", skip_range_min = 1, skip_range_max = 4294967296 ); ALTER SEQUENCE MySecondSequence SET OPTIONS ( skip_range_min = 1, skip_range_max = 4294967296 );
PostgreSQL
CREATE SEQUENCE MyFirstSequence BIT_REVERSED_POSITIVE SKIP RANGE 1 4294967296; ALTER SEQUENCE MySecondSequence SKIP RANGE 1 4294967296;
Se você estiver usando colunas IDENTITY
para gerar automaticamente valores inteiros para as colunas principais, defina os intervalos de
ignoração:
GoogleSQL
Para definir um intervalo de saltos, use o comando
GENERATED BY DEFAULT AS IDENTITY
:
ALTER DATABASE db SET OPTIONS (
default_sequence_kind = 'bit_reversed_positive',
);
CREATE TABLE MyFirstTable (
Id INT64 GENERATED BY DEFAULT AS IDENTITY (SKIP RANGE 1, 4294967296),
Name STRING(MAX),
) PRIMARY KEY (Id);
ALTER TABLE MyFirstTable ALTER COLUMN Id ALTER IDENTITY SET SKIP RANGE 1, 4294967296;
PostgreSQL
Para definir um intervalo de saltos, use o comando
GENERATED BY DEFAULT AS IDENTITY
:
ALTER DATABASE db
SET spanner.default_sequence_kind = 'bit_reversed_positive';
CREATE TABLE MyFirstTable (
Id bigint GENERATED BY DEFAULT AS IDENTITY (SKIP RANGE 1 4294967296),
Name text,
PRIMARY KEY (Id)
);
ALTER TABLE MyFirstTable ALTER COLUMN Id SET SKIP RANGE 1 4294967296;
Migrar colunas de chaves com bits invertidos
Se você já inverteu os bits dos valores de chave para evitar problemas de ponto de acesso no banco de dados de origem, também é possível usar uma sequência positiva com inversão de bits do Spanner (GoogleSQL, PostgreSQL) para continuar gerando esses valores. Para evitar a geração de valores duplicados, você pode configurar a sequência para iniciar o contador em um número personalizado.
Por exemplo, se você inverter os números de 1 a 1.000 para gerar valores de chave primária, a sequência do Spanner poderá iniciar o contador em qualquer número maior que 10.000. Como alternativa, escolha um número alto para deixar um buffer para novas gravações que ocorrem no banco de dados de origem após a migração de dados. No exemplo abaixo, os contadores começam em 11.000:
GoogleSQL
CREATE SEQUENCE MyFirstSequence OPTIONS ( sequence_kind = "bit_reversed_positive", start_with_counter = 11000 ); ALTER SEQUENCE MySecondSequence SET OPTIONS ( start_with_counter = 11000 );
PostgreSQL
CREATE SEQUENCE MyFirstSequence BIT_REVERSED_POSITIVE START COUNTER 11000; ALTER SEQUENCE MySecondSequence RESTART COUNTER 11000;
Se você estiver usando colunas IDENTITY
para gerar automaticamente valores inteiros para as colunas principais, defina um contador de início:
GoogleSQL
Para definir um contador de início, use o
comando
GENERATED BY DEFAULT AS IDENTITY
:
ALTER DATABASE db SET OPTIONS (
default_sequence_kind = 'bit_reversed_positive',
);
CREATE TABLE MyFirstTable (
Id INT64 GENERATED BY DEFAULT AS IDENTITY (START COUNTER WITH 11000),
Name STRING(MAX),
) PRIMARY KEY (Id);
ALTER TABLE MyFirstTable ALTER COLUMN Id ALTER IDENTITY RESTART COUNTER WITH 11000;
PostgreSQL
Para definir um contador de início, use o
comando
GENERATED BY DEFAULT AS IDENTITY
:
ALTER DATABASE db
SET spanner.default_sequence_kind = 'bit_reversed_positive';
CREATE TABLE MyFirstTable (
Id bigint GENERATED BY DEFAULT AS IDENTITY (START COUNTER WITH 11000),
Name text,
PRIMARY KEY (Id)
);
ALTER TABLE MyFirstTable ALTER COLUMN Id RESTART COUNTER WITH 11000;