Migrer de PostgreSQL vers Cloud Spanner

Sur cette page, vous trouverez des instructions concernant la migration d'une base de données PostgreSQL vers Cloud Spanner. La page décrit plusieurs aspects de la migration de PostgreSQL vers Cloud Spanner :

  • Mapper un schéma PostgreSQL sur un schéma Cloud Spanner
  • Créer une instance ainsi qu'une base de données et un schéma Cloud Spanner
  • Retravailler l'application pour qu'elle fonctionne avec votre base de données Cloud Spanner
  • Effectuer la migration des données
  • Vérifier le nouveau système et le passer à l'état de production

Elle fournit également des exemples de schémas utilisant des tables de la base de données PostgreSQL MusicBrainz.

Mapper votre schéma PostgreSQL sur Cloud Spanner

La première étape du transfert d’une base de données de PostgreSQL vers Cloud Spanner consiste à déterminer les modifications à apporter au schéma. Utilisez pg_dump pour créer des instructions DDL (Data Definition Language) définissant les objets de votre base de données PostgreSQL, puis modifiez-les comme décrit dans les sections suivantes. Une fois les instructions DDL modifiées, utilisez-les pour créer votre base de données dans une instance Cloud Spanner.

Types de données

Le tableau suivant décrit les correspondances entre les types de données PostgreSQL et les types de données Cloud Spanner. Dans vos instructions DDL, modifiez les données de type PostgreSQL en données de type Cloud Spanner.

PostgreSQL Cloud Spanner
Bigint

int8

INT64
Bigserial

serial8

INT64
bit [ (n) ] ARRAY<BOOL>
bit varying [ (n) ]

varbit [ (n) ]

ARRAY<BOOL>
Boolean

bool

BOOL
box ARRAY<FLOAT64>
bytea BYTES
character [ (n) ]

char [ (n) ]

STRING
character varying [ (n) ]

varchar [ (n) ]

STRING
cidr STRING, au format CIDR standard.
circle ARRAY<FLOAT64>
date DATE
double precision

float8

FLOAT64
inet STRING
Integer

int

int4

INT64
interval[ fields ] [ (p) ] INT64 pour préciser une valeur en millisecondes ou STRING pour utiliser un format d'intervalle défini par l'application.
json STRING
jsonb BYTES
line ARRAY<FLOAT64>
lseg ARRAY<FLOAT64>
macaddr STRING, au format d'adresse MAC standard.
money INT64, ou STRING pour les nombres de précision arbitraire.
numeric [ (p, s) ]

decimal [ (p, s) ]

Dans PostgreSQL, les types de données NUMERIC et DECIMAL acceptent jusqu'à 217 chiffres dans les paramètres de précision et 214 - 1 chiffres dans les paramètres d'échelle, comme défini dans la déclaration de colonne.

Le type de données Spanner NUMERIC accepte jusqu'à 38 chiffres dans les paramètres de précision et 9 chiffres décimaux dans les paramètres d'échelle.

Si vous avez besoin d'une plus grande précision, consultez la section Stocker des données numériques de précision arbitraire pour découvrir d'autres mécanismes.
path ARRAY<FLOAT64>
pg_lsn Ce type de données est spécifique à PostgreSQL. Il n'y a donc pas d'équivalent Cloud Spanner.
point ARRAY<FLOAT64>
polygon ARRAY<FLOAT64>
Real

float4

FLOAT64
Smallint

int2

INT64
Smallserial

serial2

INT64
Serial

serial4

INT64
text STRING
time [ (p) ] [ without time zone ] STRING, au format HH:MM:SS.sss.
time [ (p) ] with time zone

timetz

STRING, au format HH:MM:SS.sss+ZZZZ. Vous pouvez également diviser ces données en deux colonnes, l'une de type TIMESTAMP et l'autre contenant le fuseau horaire.
timestamp [ (p) ] [ without time zone ] Aucun équivalent. Vous pouvez stocker ces données en tant que STRING ou TIMESTAMP, à votre guise.
timestamp [ (p) ] with time zone

timestamptz

TIMESTAMP
tsquery Aucun équivalent. Définissez plutôt un mécanisme de stockage dans votre application.
tsvector Aucun équivalent. Définissez plutôt un mécanisme de stockage dans votre application.
txid_snapshot Aucun équivalent. Définissez plutôt un mécanisme de stockage dans votre application.
uuid STRING ou BYTES
xml STRING

Clés primaires

Pour les tables de votre base de données Cloud Spanner que vous ajoutez fréquemment, évitez d'utiliser des clés primaires qui augmentent ou diminuent de façon linéaire. Cette approche crée en effet des hotspots pendant les écritures. Modifiez plutôt les instructions DDL CREATE TABLE afin qu'elles utilisent les stratégies de clé primaire compatibles. Il est important de concevoir le schéma de façon soignée, car vous ne pourrez plus ajouter ni supprimer de colonne de clé primaire une fois la table créée.

Pendant la migration, vous devrez peut-être conserver certaines clés entières croissantes monotones. Si vous devez conserver ces types de clés sur une table fréquemment modifiée rassemblant de nombreuses opérations sur ces clés, vous pouvez éviter de créer des hotspots en ajoutant à la clé existante un préfixe pseudo-aléatoire. Cette technique amène Cloud Spanner à redistribuer les lignes. Pour en savoir plus sur l'utilisation de cette approche, consultez l'article Ce que les administrateurs de base de données doivent savoir sur Cloud Spanner, partie 1 : Clés et index.

Clés étrangères et intégrité du référentiel

En savoir plus sur la prise en charge des clés étrangères dans Cloud Spanner.

Index

Les index B-tree PostgreSQL sont semblables aux index secondaires dans Cloud Spanner. Dans une base de données Cloud Spanner, vous utilisez des index secondaires pour indexer les colonnes couramment recherchées afin d'obtenir de meilleures performances, et pour remplacer les contraintes uniques spécifiées dans vos tables. Par exemple, imaginons que votre DDL PostgreSQL affiche l'instruction suivante :

 CREATE TABLE customer (
    id CHAR (5) PRIMARY KEY,
    first_name VARCHAR (50),
    last_name VARCHAR (50),
    email VARCHAR (50) UNIQUE
 );

Vous utiliseriez alors l'instruction suivante dans le DDL Cloud Spanner :

CREATE TABLE customer (
   id STRING(5),
   first_name STRING(50),
   last_name STRING(50),
   email STRING(50)
   ) PRIMARY KEY (id);

CREATE UNIQUE INDEX customer_emails ON customer(email);

Vous pouvez trouver les index de toutes vos tables PostgreSQL en exécutant la méta-commande \di dans psql.

Une fois que vous avez déterminé les index dont vous avez besoin, ajoutez des instructions CREATE INDEX pour les créer. Pour ce faire, suivez les instructions de la section Créer des index.

Cloud Spanner implémente les index sous forme de tables. Par conséquent, l'indexation de colonnes de façon croissante et linéaire (comme celles contenant des données TIMESTAMP) peut provoquer un hotspot. Pour en savoir plus sur la façon d'éviter les hotspots, consultez l'article Ce que les administrateurs de base de données doivent savoir sur Cloud Spanner, partie 1 : Clés et index.

Vérifier les contraintes

En savoir plus sur la compatibilité de la contrainte CHECK dans Cloud Spanner

Autres objets de base de données

Vous devez créer la fonctionnalité des objets suivants dans la logique de votre application :

  • Vues
  • Déclencheurs
  • Procédures stockées
  • Fonctions définies par l'utilisateur
  • Colonnes utilisant des types de données serial en tant que générateurs de séquence

Pour la migration de cette fonctionnalité dans la logique de l'application, tenez compte des conseils suivants :

Créer une instance Cloud Spanner

Une fois vos instructions DDL modifiées pour qu'elles soient conformes aux exigences du schéma Cloud Spanner, utilisez-les pour créer une base de données dans Cloud Spanner.

  1. Créez une instance Cloud Spanner. Suivez les instructions fournies sur la page Instances pour déterminer la configuration régionale appropriée, ainsi que le nombre de nœuds nécessaire à l'atteinte de vos objectifs de performances.

  2. Créez la base de données à l'aide de Google Cloud Console ou de l'outil de ligne de commande gcloud :

Console

  1. Accéder à la page Instances
  2. Cliquez sur le nom de l'instance dans laquelle vous souhaitez créer l'exemple de base de données pour ouvrir la page Détails de l'instance.
  3. Cliquez sur Créer une base de données.
  4. Saisissez un nom pour la base de données, puis cliquez sur Continuer.
  5. Dans la section Définir le schéma de votre base de données, cliquez sur le bouton Modifier sous forme de texte.
  6. Copiez et collez vos instructions DDL dans le champ Instructions DDL.
  7. Cliquez sur Créer.

gcloud

  1. Installez l'outil gcloud.
  2. Utilisez la commande gcloud spanner databases create pour créer la base de données :
    gcloud spanner databases create DATABASE_NAME --instance=INSTANCE_NAME
    --ddl='DDL1' --ddl='DDL2'
    
  • DATABASE_NAME correspond au nom de votre base de données.
  • INSTANCE_NAME correspond à l'instance Cloud Spanner que vous avez créée.
  • DDLn correspond à vos instructions LDD modifiées.

Une fois la base de données créée, suivez les instructions de la page Attribuer des rôles IAM pour créer des comptes d'utilisateurs et accorder des autorisations à l'instance et à la base de données Cloud Spanner.

Retravailler les applications et les couches d'accès aux données

En plus du code nécessaire pour remplacer les objets de base de données précédents, vous devez ajouter une logique d'application pour gérer les fonctionnalités suivantes :

  • Hachage de clés primaires pour les écritures, pour les tables avec des taux d'écriture élevés en clés séquentielles
  • Validation des données pour le moment non couvertes par les contraintes CHECK.
  • Vérifications de l'intégrité du référentiel pour le moment non couvertes par les clés étrangères, l'entrelacement de tables ou la logique de l'application, y compris les fonctionnalités gérées par les déclencheurs du schéma PostgreSQL

Nous vous recommandons d'utiliser le processus suivant lors du retravail :

  1. Trouvez tout le code de votre application qui accède à la base de données, puis retravaillez-le en un seul module ou une seule bibliothèque. De cette façon, vous savez exactement quel code accède à la base de données, et donc exactement quel code doit être modifié.
  2. Écrivez du code qui lit et écrit sur l'instance Cloud Spanner, en fournissant une fonctionnalité parallèle au code d'origine qui lit et écrit sur PostgreSQL. Pendant les écritures, actualisez la ligne entière, et non pas uniquement les colonnes qui ont été modifiées, pour vous assurer que les données sont identiques dans Cloud Spanner et dans PostgreSQL.
  3. Écrivez un code qui remplace la fonctionnalité des objets et fonctions de la base de données non disponibles dans Cloud Spanner.

Effectuer la migration des données

Une fois votre base de données Cloud Spanner créée et le code de votre application retravaillé, vous pouvez réaliser la migration de vos données vers Cloud Spanner.

  1. Utilisez la commande PostgreSQL COPY pour transférer les données vers des fichiers .csv.
  2. Importez les fichiers .csv dans Cloud Storage.

    1. Créez un bucket Cloud Storage.
    2. Dans la console Cloud Storage, cliquez sur le nom du bucket pour ouvrir son navigateur.
    3. Cliquez sur Importer des fichiers.
    4. Accédez au répertoire contenant les fichiers .csv et sélectionnez-les.
    5. Cliquez sur Ouvrir.
  3. Créez une application pour importer des données dans Cloud Spanner. Cette application peut utiliser Dataflow ou directement les bibliothèques clientes. Assurez-vous de suivre les instructions des bonnes pratiques de chargement groupé des données pour obtenir des performances optimales.

Test

Testez toutes les fonctions de l'application sur l'instance Cloud Spanner pour vérifier qu'elles fonctionnent comme prévu. Exécutez des charges de travail en production pour vous assurer que les performances répondent bien à vos besoins. Modifiez le nombre de nœuds selon vos besoins pour atteindre vos objectifs de performances.

Passer au nouveau système

Une fois les tests d'application initiaux terminés, activez le nouveau système en utilisant l'un des processus suivants. La migration hors ligne est le moyen le plus simple d'effectuer la migration. Toutefois, cette approche rend votre application indisponible pendant un certain temps, et vous ne pourrez pas réaliser de rollback si vous détectez des problèmes de données ultérieurement. Pour effectuer une migration hors ligne, procédez comme suit :

  1. Supprimez toutes les données de la base de données Cloud Spanner.
  2. Fermez l’application qui cible la base de données PostgreSQL.
  3. Exportez toutes les données de la base de données PostgreSQL, puis importez-les dans la base de données Cloud Spanner, comme décrit dans la section Effectuer la migration des données.
  4. Démarrez l'application qui cible la base de données Cloud Spanner.

    Flux de données de la migration hors ligne

La migration en direct est une solution possible. Cela implique toutefois d'apporter des modifications importantes à votre application pour qu'elle accepte la migration.

Exemples de migration de schéma

Ces exemples présentent les instructions CREATE TABLE pour plusieurs tables du schéma de la base de données PostgreSQL MusicBrainz. Chaque exemple inclut à la fois le schéma PostgreSQL et le schéma Cloud Spanner.

Table "artist_credit"

Version PostgreSQL :

CREATE TABLE artist_credit (
  id SERIAL,
  name VARCHAR NOT NULL,
  artist_count SMALLINT NOT NULL,
  ref_count INTEGER DEFAULT 0,
  created TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

Version Cloud Spanner :

CREATE TABLE artist_credit (
  hashed_id STRING(4),
  id INT64,
  name STRING(MAX) NOT NULL,
  artist_count INT64 NOT NULL,
  ref_count INT64,
  created TIMESTAMP OPTIONS (
     allow_commit_timestamp = true
  ),
) PRIMARY KEY(hashed_id, id);

Table "recording"

Version PostgreSQL :

CREATE TABLE recording (
  id SERIAL,
  gid UUID NOT NULL,
  name VARCHAR NOT NULL,
  artist_credit INTEGER NOT NULL, -- references artist_credit.id
  length INTEGER CHECK (length IS NULL OR length > 0),
  comment VARCHAR(255) NOT NULL DEFAULT '',
  edits_pending INTEGER NOT NULL DEFAULT 0 CHECK (edits_pending >= 0),
  last_updated TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  video BOOLEAN NOT NULL DEFAULT FALSE
);

Version Cloud Spanner :

CREATE TABLE recording (
  hashed_id STRING(36),
  id INT64,
  gid STRING(36) NOT NULL,
  name STRING(MAX) NOT NULL,
  artist_credit_hid STRING(36) NOT NULL,
  artist_credit_id INT64 NOT NULL,
  length INT64,
  comment STRING(255) NOT NULL,
  edits_pending INT64 NOT NULL,
  last_updated TIMESTAMP OPTIONS (
     allow_commit_timestamp = true
  ),
  video BOOL NOT NULL,
) PRIMARY KEY(hashed_id, id);

Table "recording-alias"

Version PostgreSQL :

CREATE TABLE recording_alias (
  id SERIAL, --PK
  recording INTEGER NOT NULL, -- references recording.id
  name VARCHAR NOT NULL,
  locale TEXT,
  edits_pending INTEGER NOT NULL DEFAULT 0 CHECK (edits_pending >=0),
  last_updated TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  type INTEGER, -- references recording_alias_type.id
  sort_name VARCHAR NOT NULL,
  begin_date_year SMALLINT,
  begin_date_month SMALLINT,
  begin_date_day SMALLINT,
  end_date_year SMALLINT,
  end_date_month SMALLINT,
  end_date_day SMALLINT,
  primary_for_locale BOOLEAN NOT NULL DEFAULT false,
  ended BOOLEAN NOT NULL DEFAULT FALSE
  -- CHECK constraint skipped for brevity
);

Version Cloud Spanner :

CREATE TABLE recording_alias (
  hashed_id STRING(36)  NOT NULL,
  id INT64  NOT NULL,
  alias_id INT64,
  name STRING(MAX)  NOT NULL,
  locale STRING(MAX),
  edits_pending INT64  NOT NULL,
  last_updated TIMESTAMP NOT NULL OPTIONS (
     allow_commit_timestamp = true
  ),
  type INT64,
  sort_name STRING(MAX)  NOT NULL,
  begin_date_year INT64,
  begin_date_month INT64,
  begin_date_day INT64,
  end_date_year INT64,
  end_date_month INT64,
  end_date_day INT64,
  primary_for_locale BOOL NOT NULL,
  ended BOOL NOT NULL,
) PRIMARY KEY(hashed_id, id, alias_id),
 INTERLEAVE IN PARENT recording ON DELETE NO ACTION;