Esegui la migrazione delle chiavi primarie

Questo documento fornisce istruzioni per eseguire la migrazione delle chiavi primarie dalle tabelle del database di origine a Spanner. Devi conoscere le informazioni disponibili nella Panoramica della migrazione delle chiavi principali.

Prima di iniziare

  • Per ottenere le autorizzazioni necessarie per la migrazione delle chiavi primarie a Spanner, chiedi all'amministratore di concederti Ruolo IAM Amministratore database Cloud Spanner (roles/spanner.databaseAdmin) per l'istanza.

Eseguire la migrazione delle chiavi sequenziali generate automaticamente

Se esegui la migrazione da un database che utilizza chiavi monotoiche sequenziali, ad esempio AUTO_INCREMENT in MySQL, SERIAL in PostgreSQL o il tipo IDENTITY standard in SQL Server o Oracle, Prendi in considerazione la seguente strategia di migrazione di alto livello:

  1. In Spanner, replica la struttura della tabella dal tuo database di origine utilizzando una chiave primaria intera.
  2. Per ogni colonna di Spanner che contiene valori sequenziali, crea una sequenza e assegna GET_NEXT_SEQUENCE_VALUE (GoogleSQL, PostgreSQL) come valore predefinito per la colonna.
  3. Esegui la migrazione dei dati esistenti con le chiavi originali dall'origine in Spanner. Valuta l'uso della classe Strumento di migrazione di Spanner o un modello di Dataflow.
  4. Se vuoi, puoi stabilire vincoli di chiavi esterne per eventuali tabelle dipendenti.
  5. Prima di inserire nuovi dati, regola Spanner per saltare l'intervallo di coppie chiave-valore esistenti.
  6. Inserisci nuovi dati, consentendo alla sequenza di generare automaticamente chiavi univoche.

Flusso di lavoro di migrazione di esempio

Il codice seguente definisce la struttura della tabella e la sequenza correlata in Spanner utilizzando un oggetto SEQUENCE e lo imposta come valore principale predefinito della tabella di destinazione:

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)
);

L'opzione bit_reversed_positive indica che i valori generati sono di tipo INT64, sono maggiori di zero e non sono sequenziali.

Quando esegui la migrazione delle righe esistenti dal database di origine Spanner, le chiavi primarie rimangono invariate.

Per i nuovi inserimenti che non specificano una chiave primaria, Spanner recupera automaticamente un nuovo valore chiamando la funzione GET_NEXT_SEQUENCE_VALUE()(GoogleSQL o PostgreSQL).

Questi valori sono distribuiti uniformemente nell'intervallo [1, 263] e potrebbero verificarsi possibili collisioni con le chiavi esistenti. Per evitare che ciò accada, puoi configura la sequenza utilizzando ALTER_SEQUENCE (GoogleSQL o PostgreSQL) per saltare l'intervallo e i valori coperti dalle chiavi esistenti.

Supponiamo che sia stata eseguita la migrazione della tabella singers da PostgreSQL, dove la sua chiave primaria singer_id è di tipo SERIAL. Il seguente PostgreSQL mostra il DDL del tuo database di origine:

PostgreSQL

CREATE TABLE Singers (
SingerId SERIAL PRIMARY KEY,
Name varchar(1024),
Biography varchar
);

I valori chiave primaria sono in aumento monotonico. Dopo la migrazione, puoi recuperare il valore massimo della chiave primaria singer_id su Spanner. Usa il seguente codice in Spanner:

GoogleSQL

SELECT MAX(SingerId) FROM Singers;

PostgreSQL

SELECT MAX(SingerId) FROM Singers;

Supponiamo che il valore restituito sia 20.000. Puoi configurare la sequenza Spanner per saltare l'intervallo [1, 21000]. Le 1000 aggiuntive fungono da del buffer per supportare le scritture sul database di origine dopo la migrazione iniziale. Le nuove chiavi generate in Spanner non sono in conflitto con l'intervallo di chiavi primarie generate nel database PostgreSQL di origine. Utilizza il seguente codice in Spanner:

GoogleSQL

ALTER SEQUENCE SingerIdSequence SET OPTIONS (
skip_range_min = 1,
skip_range_max = 21000
);

PostgreSQL

ALTER SEQUENCE SingerIdSequence SKIP RANGE 1 21000;

utilizza Spanner e il database di origine

Puoi utilizzare il concetto di intervallo di ignoramenti per supportare scenari in cui Spanner o il tuo database di origine generano chiavi primarie, ad esempio per abilitare la replica in entrambe le direzioni per il ripristino di emergenza durante il passaggio di una migrazione.

Per supportare questa operazione, entrambi i database generano chiavi primarie e i dati vengono sincronizzati tra di loro. Puoi configurare ciascun database per creare in intervalli di chiavi non sovrapposti. Quando definisci un intervallo per il database di origine, puoi configurare la sequenza Spanner in modo che lo ignori.

Ad esempio, dopo la migrazione dell'applicazione di tracce musicali, replica i dati da PostgreSQL a Spanner per ridurre il tempo necessario per il passaggio.

Dopo aver aggiornato e testato l'applicazione su Spanner, puoi non usare più il database PostgreSQL di origine e usare Spanner, rendendolo il sistema di registrazione per gli aggiornamenti e le nuove chiavi primarie. Una volta che Spanner prende il controllo, puoi invertire il flusso di dati tra i database nell'istanza PostgreSQL.

Supponi che il database PostgreSQL di origine utilizzi SERIAL chiavi primarie, che sono Numeri interi con segno a 32 bit. Le chiavi principali di Spanner sono numeri di 64 bit più grandi. In PostgreSQL, modifica la colonna di chiave primaria in una colonna a 64 bit o bigint. Utilizza il seguente codice sul tuo database PostgreSQL di origine:

PostgreSQL

ALTER TABLE Singers ALTER COLUMN SingerId TYPE bigint;

Puoi impostare un vincolo CHECK per la tabella nel database PostgreSQL di origine per garantire che i valori della chiave primaria SingerId siano sempre minori di o uguale a 231-1. Utilizza il seguente codice nel database PostgreSQL di origine:

PostgreSQL

ALTER TABLE Singers ADD CHECK (SingerId <= 2147483647);

In Spanner, possiamo modificare la sequenza in modo da saltare l'intervallo [1, 231-1]. Usa il seguente codice in 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;

Il database PostgreSQL di origine genera sempre chiavi con un numero intero a 32 bit mentre le chiavi Spanner sono limitate al numero intero a 64 bit maggiore di tutti i valori interi a 32 bit. In questo modo, entrambi i database possono generare in modo indipendente chiavi primarie che non entrano in conflitto.

Esegui la migrazione delle colonne delle chiavi UUID

Le chiavi UUIDv4 sono effettivamente univoche indipendentemente da dove vengono generate. Le chiavi UUID generate altrove si integrano con le nuove chiavi UUID generate in Spanner.

Considera la seguente strategia di alto livello per eseguire la migrazione delle chiavi UUID a Spanner:

  1. Definisci le chiavi UUID in Spanner utilizzando colonne di stringhe con un'espressione predefinita. Utilizza la funzione GENERATE_UUID() (GoogleSQL, PostgreSQL).
  2. Esporta i dati dal sistema di origine, serializzando le chiavi UUID come stringhe.
  3. Importa le chiavi principali in Spanner.
  4. (Facoltativo) Abilita le chiavi esterne.

Ecco un esempio di flusso di lavoro per la migrazione:

In Spanner, definisci una colonna di chiave primaria UUID come STRING o Digita TEXT e assegna GENERATE_UUID() (GoogleSQL o PostgreSQL) come valore predefinito. Esegui la migrazione di tutti dal database di origine a Spanner. Dopo la migrazione, man mano che vengono inserite nuove righe, Spanner chiama GENERATE_UUID() per generare nuovi valori UUID per le chiavi principali. Ad esempio, la chiave primaria FanClubId riceve un valore UUIDv4 quando viene inserita una nuova riga nella tabella FanClubs. Utilizza il seguente codice in 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');

Esegui la migrazione delle tue chiavi primarie

La tua applicazione potrebbe basarsi sull'ordine chiave primaria per determinare quanto è recente il ovvero i dati appena creati. Per utilizzare le chiavi sequenziali generate esternamente in Spanner, puoi creare una chiave composta che combina un valore distribuito in modo uniforme, ad esempio un hash, come primo componente e la chiave sequenziale come secondo componente. In questo modo, puoi conservare i valori delle chiavi sequenziali, senza creare hot spot su larga scala. Considera il seguente flusso di lavoro di migrazione:

Supponi di dover eseguire la migrazione di una tabella MySQL students con un AUTO_INCREMENT chiave primaria per Spanner. Utilizza il seguente codice nel database MySQL di origine:

MySQL

CREATE TABLE Students (
StudentId INT NOT NULL AUTO_INCREMENT,
Info VARCHAR(2048),
PRIMARY KEY (StudentId)
);

In Spanner, puoi aggiungere una colonna StudentIdHash generata creando un hash di la colonna StudentId. Ad esempio:

  StudentIdHash = FARM_FINGERPRINT(CAST(StudentId AS STRING))

In Spanner puoi utilizzare il seguente codice:

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)
);

Passaggi successivi