Migrer des clés primaires

Cette page explique comment migrer les clés primaires des tables de votre base de données source vers les bases de données Spanner au dialecte GoogleSQL et les bases de données au dialecte PostgreSQL. Avant d'effectuer les procédures décrites sur cette page, consultez la présentation de la migration des clés primaires.

Avant de commencer

  • Pour obtenir les autorisations nécessaires pour migrer des clés primaires vers Spanner, demandez à votre administrateur de vous accorder le rôle IAM Administrateur de bases de données Cloud Spanner (roles/spanner.databaseAdmin) sur l'instance.

Migrer des clés séquentielles générées automatiquement

Si vous effectuez la migration à partir d'une base de données qui utilise des clés monotones séquentielles, telles que AUTO_INCREMENT dans MySQL, SERIAL dans PostgreSQL ou le type IDENTITY standard dans SQL Server ou Oracle, envisagez la stratégie de migration d'ensemble suivante:

  1. Dans Spanner, répliquez la structure de table à partir de votre base de données source à l'aide d'une clé primaire entière.
  2. Pour chaque colonne de Spanner contenant des valeurs séquentielles, créez une séquence et attribuez la fonction GET_NEXT_SEQUENCE_VALUE ( GoogleSQL, PostgreSQL) comme valeur par défaut de la colonne.
  3. Migrez les données existantes avec les clés d'origine de la base de données source vers Spanner. Envisagez d'utiliser l'outil de migration Spanner ou un modèle Dataflow.
    1. Vous pouvez également définir des contraintes de clé étrangère pour toutes les tables dépendantes.
  4. Avant d'insérer de nouvelles données, ajustez la séquence Spanner pour ignorer la plage des valeurs de clé existantes.
  5. Insérez de nouvelles données, ce qui permet à la séquence de générer automatiquement des clés uniques.

Exemple de workflow de migration

Le code suivant définit la structure de la table et la séquence associée dans Spanner à l'aide d'un objet SEQUENCE et définit l'objet comme valeur primaire par défaut de la table de destination:

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'option bit_reversed_positive indique que les valeurs générées par la séquence sont de type INT64, sont supérieures à zéro et ne sont pas séquentielles.

Lorsque vous migrez des lignes existantes de votre base de données source vers Spanner, les clés primaires restent inchangées.

Pour les nouvelles insertions qui ne spécifient pas de clé primaire, Spanner récupère automatiquement une nouvelle valeur en appelant la fonction GET_NEXT_SEQUENCE_VALUE(GoogleSQL ou PostgreSQL).

Ces valeurs sont distribuées uniformément sur la plage [1, 263], et des collisions peuvent se produire avec les clés existantes. Pour éviter cela, vous pouvez configurer la séquence à l'aide de ALTER_SEQUENCE (GoogleSQL ou PostgreSQL) pour ignorer la plage de valeurs couverte par les clés existantes.

Supposons que la table singers ait été migrée depuis PostgreSQL, où sa clé primaire singer_id est de type SERIAL. Le code PostgreSQL suivant affiche le DDL de votre base de données source:

PostgreSQL

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

Les valeurs de la clé primaire augmentent de manière monotone. Après la migration, vous pouvez récupérer la valeur maximale de la clé primaire singer_id sur Spanner. Utilisez le code suivant dans Spanner:

GoogleSQL

SELECT MAX(SingerId) FROM Singers;

PostgreSQL

SELECT MAX(SingerId) FROM Singers;

Supposons que la valeur renvoyée soit 20 000. Vous pouvez configurer la séquence Spanner pour ignorer la plage [1, 21000]. Les 1 000 éléments supplémentaires servent de tampon pour les écritures dans la base de données source après la migration initiale. Les nouvelles clés générées dans Spanner ne sont pas en conflit avec la plage de clés primaires générées dans la base de données PostgreSQL source. Utilisez le code suivant dans Spanner:

GoogleSQL

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

PostgreSQL

ALTER SEQUENCE SingerIdSequence SKIP RANGE 1 21000;

Utiliser Spanner et votre base de données source

Vous pouvez utiliser le concept de plage de saut pour prendre en charge les scénarios où Spanner ou votre base de données source génère des clés primaires, par exemple pour activer la réplication dans les deux sens pour la reprise après sinistre lors d'un passage à une nouvelle version.

Pour ce faire, les deux bases de données génèrent des clés primaires et les données sont synchronisées entre elles. Vous pouvez configurer chaque base de données pour créer des clés primaires dans des plages de clés non superposées. Lorsque vous définissez une plage pour votre base de données source, vous pouvez configurer la séquence Spanner pour ignorer cette plage.

Par exemple, après la migration de l'application de titres musicaux, répliquez les données de PostgreSQL vers Spanner pour réduire le temps de transition.

Une fois que vous avez mis à jour et testé l'application sur Spanner, vous pouvez cesser d'utiliser votre base de données PostgreSQL source et utiliser Spanner, ce qui en fait le système d'enregistrement des mises à jour et des nouvelles clés primaires. Lorsque Spanner prend le relais, vous pouvez inverser le flux de données entre les bases de données dans l'instance PostgreSQL.

Supposons que votre base de données PostgreSQL source utilise des clés primaires SERIAL, qui sont des entiers signés 32 bits. Les clés primaires Spanner sont des nombres de 64 bits plus importants. Dans PostgreSQL, modifiez la colonne de clé primaire pour qu'elle soit une colonne 64 bits ou bigint. Utilisez le code suivant sur votre base de données PostgreSQL source:

PostgreSQL

ALTER TABLE Singers ALTER COLUMN SingerId TYPE bigint;

Vous pouvez définir une contrainte CHECK sur la table dans la base de données PostgreSQL source pour vous assurer que les valeurs de la clé primaire SingerId sont toujours inférieures ou égales à 231-1.

Utilisez le code suivant sur votre base de données PostgreSQL source:

PostgreSQL

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

Dans Spanner, nous pouvons modifier la séquence pour ignorer la plage [1, 231-1].

Utilisez le code suivant dans 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;

Votre base de données PostgreSQL source génère toujours des clés dans l'espace d'entiers 32 bits, tandis que les clés Spanner sont limitées à l'espace d'entiers 64 bits, plus grand que toutes les valeurs d'entiers 32 bits. Cela garantit que vos deux bases de données peuvent générer indépendamment des clés primaires qui ne se chevauchent pas.

Migrer les colonnes de clé UUID

Les clés UUIDv4 sont effectivement uniques, quel que soit l'endroit où elles sont générées. Les clés UUID générées ailleurs s'intègrent aux nouvelles clés UUID générées dans Spanner.

Envisagez la stratégie d'ordre général suivante pour migrer les clés UUID vers Spanner:

  1. Définissez vos clés UUID dans Spanner à l'aide de colonnes de chaîne avec une expression par défaut. Utilisez la fonction GENERATE_UUID() (Google SQL, PostgreSQL).
  2. Exportez les données du système source, en sérialisant les clés UUID sous forme de chaînes.
  3. Importez les clés primaires dans Spanner.
  4. Facultatif: Activez les clés étrangères.

Voici un exemple de workflow de migration:

Dans Spanner, définissez une colonne de clé primaire UUID comme type STRING ou TEXT, puis attribuez GENERATE_UUID() (GoogleSQL ou PostgreSQL) comme valeur par défaut. Migrez toutes les données de votre base de données source vers Spanner. Après la migration, à mesure que de nouvelles lignes sont insérées, Spanner appelle GENERATE_UUID() pour générer de nouvelles valeurs UUID pour les clés primaires. Par exemple, la clé primaire FanClubId reçoit une valeur UUIDv4 lorsqu'une nouvelle ligne est insérée dans la table FanClubs. Utilisez le code suivant dans 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');

Migrer vos propres clés primaires

Votre application peut s'appuyer sur l'ordre de la clé primaire pour déterminer la fraîcheur des données ou pour séquencer les données nouvellement créées. Pour utiliser des clés séquentielles générées en externe dans Spanner, vous pouvez créer une clé composite qui combine une valeur distribuée uniformément, telle qu'un hachage, comme premier composant et votre clé séquentielle comme deuxième composant. Vous pouvez ainsi conserver les valeurs de clé séquentielles, sans créer de points chauds à grande échelle. Considérons le workflow de migration suivant:

Supposons que vous deviez migrer une table MySQL students avec une clé primaire AUTO_INCREMENT vers Spanner. Utilisez le code suivant dans votre base de données MySQL source:

MySQL

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

Dans Spanner, vous pouvez ajouter une colonne générée StudentIdHash en créant un hachage de la colonne StudentId. Exemple :

StudentIdHash = FARM_FINGERPRINT(CAST(StudentId AS STRING))

Vous pouvez utiliser le code suivant dans 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)
);

Migrer des colonnes de clés séquentielles

Si votre système de base de données source génère des valeurs séquentielles pour une colonne clé, vous pouvez utiliser une séquence positive inversée (GoogleSQL, PostgreSQL) dans votre schéma Spanner pour générer des valeurs réparties uniformément sur l'espace de nombres entiers 64 bits positifs. Pour empêcher la séquence Spanner de générer une valeur qui chevauche une valeur migrée, vous pouvez définir une plage ignorée pour celle-ci.

Par exemple, vous pouvez ignorer la plage de 1 à 4 294 967 296 (2^32) pour les deux séquences suivantes, si vous savez que la base de données source ne génère que des entiers 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;

Si vous utilisez des colonnes IDENTITY pour générer automatiquement des valeurs entières pour vos colonnes clés, vous pouvez définir des plages à ignorer:

GoogleSQL

Pour définir une plage de saut, utilisez la commande 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

Pour définir une plage de saut, utilisez la commande 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;

Migrer les colonnes de clés inversées

Si vous avez déjà inversé les valeurs de clé pour éviter les problèmes de point chaud dans votre base de données source, vous pouvez également utiliser une séquence positive inversée par bits Spanner (GoogleSQL, PostgreSQL) pour continuer à générer de telles valeurs. Pour éviter de générer des valeurs en double, vous pouvez configurer la séquence pour qu'elle démarre son compteur à partir d'un nombre personnalisé.

Par exemple, si vous avez inversé les nombres de 1 à 1 000 pour générer des valeurs de clé primaire, la séquence Spanner peut démarrer son compteur à partir de n'importe quel nombre supérieur à 10 000. Vous pouvez également choisir un nombre élevé pour laisser un tampon pour les nouvelles écritures qui se produisent dans la base de données source après la migration de données. Dans l'exemple suivant, les compteurs commencent à 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;

Si vous utilisez des colonnes IDENTITY pour générer automatiquement des valeurs entières pour vos colonnes de clés, vous pouvez définir un compteur de début:

GoogleSQL

Pour définir un compteur de démarrage, utilisez la commande 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

Pour définir un compteur de démarrage, utilisez la commande 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;

Étape suivante