Migra de PostgreSQL a Cloud Spanner

En esta página, se proporcionan instrucciones para migrar una base de datos de PostgreSQL a Cloud Spanner. Describe varios aspectos de una migración de PostgreSQL a Cloud Spanner:

  • Asignar un esquema de PostgreSQL a un esquema de Cloud Spanner
  • Crear una instancia, una base de datos y un esquema de Cloud Spanner
  • Reestructurar la aplicación para que funcione con tu base de datos de Cloud Spanner
  • Migrar tus datos
  • Verificar el nuevo sistema y pasarlo al estado de producción

En esta página, también se proporcionan algunos esquemas de ejemplo que usan tablas de la base de datos de PostgreSQL de MusicBrainz.

Asigna tu esquema de PostgreSQL a Cloud Spanner

El primer paso para mover una base de datos de PostgreSQL a Cloud Spanner es determinar qué cambios de esquema debes realizar. Usa pg_dump para crear instrucciones de lenguaje de definición de datos (DDL) que definan los objetos en tu base de datos PostgreSQL y, luego, modifica las instrucciones como se describe en las siguientes secciones. Después de actualizar las instrucciones de DLL, úsalas para crear tu base de datos en una instancia de Cloud Spanner.

Tipos de datos

En la siguiente tabla, se describe cómo se asignan los tipos de datos de PostgreSQL a los tipos de datos de Cloud Spanner. Actualiza los tipos de datos en tus instrucciones de DDL de los tipos de datos de PostgreSQL a los tipos de datos de 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, con la notación CIDR estándar.
circle ARRAY<FLOAT64>
date DATE
double precision

float8

FLOAT64
inet STRING
Integer

int

int4

INT64
interval[ fields ] [ (p) ] INT64 si se almacena el valor en milisegundos o STRING si se almacena el valor en un formato de intervalo definido por la aplicación.
json STRING
jsonb BYTES
line ARRAY<FLOAT64>
lseg ARRAY<FLOAT64>
macaddr STRING, con la notación de dirección MAC estándar.
money INT64 o STRING para números de precisión arbitrarios.
numeric [ (p, s) ]

decimal [ (p, s) ]

INT64 o STRING para números de precisión arbitrarios.
path ARRAY<FLOAT64>
pg_lsn Este tipo de datos es específico de PostgreSQL, por lo que no existe un equivalente de 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, con la notación HH:MM:SS.sss.
time [ (p) ] with time zone

timetz

STRING, con la notación HH:MM:SS.sss+ZZZZ. Como alternativa, puede dividirse en dos columnas, una de tipo TIMESTAMP y otra que contiene la zona horaria.
timestamp [ (p) ] [ without time zone ] No hay equivalente. Puedes almacenar como STRING o TIMESTAMP a discreción.
timestamp [ (p) ] with time zone

timestamptz

TIMESTAMP
tsquery No hay equivalente. En su lugar, define un mecanismo de almacenamiento en tu aplicación.
tsvector No hay equivalente. En su lugar, define un mecanismo de almacenamiento en tu aplicación.
txid_snapshot No hay equivalente. En su lugar, define un mecanismo de almacenamiento en tu aplicación.
uuid STRING o BYTES
xml STRING

Claves primarias

En el caso de las tablas de tu base de datos de Cloud Spanner a las que sueles agregarte, evita usar claves primarias que aumenten o disminuyan monótonamente, ya que este enfoque genera hotspots durante las escrituras. En su lugar, modifica las instrucciones CREATE TABLE de DDL para que usen estrategias de claves primarias compatibles. Es importante diseñar el esquema con cuidado, ya que no puedes agregar ni quitar una columna de clave primaria después de crear una tabla.

Durante la migración, es posible que debas conservar algunas claves de número entero que aumentan monótonamente. Si necesitas mantener estos tipos de claves en una tabla actualizada frecuentemente con muchas operaciones en estas claves, puedes evitar crear hotspots anteponiendo la clave existente con un número seudoaleatorio. Esta técnica hace que Cloud Spanner redistribuya las filas. Para obtener más información sobre el uso de este enfoque, consulta el artículo Lo que los DBA necesitan saber sobre Cloud Spanner, parte 1: Índices y claves.

Integridad referencial y claves externas

Obtén más información sobre la compatibilidad con claves externas en Cloud Spanner.

Índices

Los índices b-tree de PostgreSQL son similares a los índices secundarios en Cloud Spanner. En una base de datos de Cloud Spanner, utiliza índices secundarios para indexar las columnas más buscadas con el fin de mejorar el rendimiento y reemplazar las restricciones únicas especificadas en tus tablas. Por ejemplo, si tu DDL de PostgreSQL tiene esta instrucción:

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

Deberías usar esta instrucción en tu DDL de 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);

Puedes encontrar los índices de cualquiera de tus tablas de PostgreSQL si ejecutas el meta-comando \di en psql.

Después de determinar los índices que necesitas, agrega instrucciones CREATE INDEX para crearlos. Sigue las instrucciones en Creación de índices.

Cloud Spanner implementa índices como tablas, por lo que indexar columnas que aumentan de forma monótona (como las que contienen datos TIMESTAMP) puede generar un hotspot. A fin de obtener más información sobre los métodos para evitar hotspots, consulta el artículo Lo que los DBA necesitan saber sobre Cloud Spanner, parte 1: Índices y claves.

Otros objetos de base de datos

Debes crear la funcionalidad de los siguientes objetos en la lógica de tu aplicación:

  • Vistas
  • Activadores
  • Procedimientos almacenados
  • Funciones definidas por el usuario (UDF)
  • Columnas que usan tipos de datos serial como generadores de secuencias

Cuando migres esta funcionalidad a la lógica de la aplicación, ten en cuenta las siguientes sugerencias:

Crea tu instancia de Cloud Spanner

Después de actualizar tus instrucciones de DDL a fin de cumplir con los requisitos del esquema de Cloud Spanner, utilízalas para crear tu base de datos en Cloud Spanner.

  1. Crea una instancia de Cloud Spanner. Sigue las instrucciones que se indican en Instancias a fin de determinar la configuración regional correcta y la cantidad de nodos necesarios para tus objetivos de rendimiento.

  2. Crea la base de datos con Google Cloud Console o la herramienta de línea de comandos de gcloud:

Console

  1. Ir a la página Instancias
  2. Haz clic en el nombre de la instancia en la que deseas crear la base de datos de ejemplo para abrir la página Detalles de la instancia.
  3. Haz clic en Crear base de datos.
  4. Escribe un nombre para la base de datos y haz clic en Continuar.
  5. En la sección Define el esquema de tu base de datos, activa o desactiva el control Editar como texto.
  6. Copia y pega tus instrucciones de DDL en el campo Instrucciones de DDL.
  7. Haz clic en Crear.

gcloud

  1. Instala la herramienta de gcloud.
  2. Usa el comando gcloud spanner databases create para crear la base de datos:
    gcloud spanner databases create DATABASE_NAME --instance=INSTANCE_NAME
    --ddl='DDL1' --ddl='DDL2'
    
  • DATABASE_NAME es el nombre de tu base de datos.
  • INSTANCE_NAME es la instancia de Cloud Spanner que creaste.
  • DDLn son tus declaraciones DDL modificadas.

Después de crear la base de datos, sigue las instrucciones en cómo aplicar funciones de IAM para crear cuentas de usuario y otorgar permisos a la instancia y base de datos de Cloud Spanner.

Reestructura las capas de aplicaciones y acceso a los datos

Además del código necesario para reemplazar los objetos de base de datos anteriores, debes agregar lógica de aplicación para manejar la siguiente funcionalidad:

  • Claves primarias hash de escrituras, tablas que tienen tasas de escritura altas para claves secuenciales.
  • Valida los datos para reemplazar las restricciones que no pudiste migrar desde el esquema de PostgreSQL.
  • Las verificaciones de integridad referencial no están cubiertas por el intercalado de tablas o la lógica de aplicación, incluida la funcionalidad manejada por activadores en el esquema de PostgreSQL.

Recomendamos usar el siguiente proceso cuando se reestructure:

  1. Busca todo el código de la aplicación que accede a la base de datos y reestructúralo en un solo módulo o biblioteca. De esta manera, sabrás exactamente qué código accede a la base de datos y, por lo tanto, qué código específico se debe modificar.
  2. Escribe código que realiza operaciones de lectura y escritura en la instancia de Cloud Spanner, que proporciona funcionalidad paralela al código original que lee y escribe en PostgreSQL. Durante las operaciones de escritura, actualiza toda la fila, no solo las columnas que se han modificado, para garantizar que los datos en Cloud Spanner sean idénticos a los de PostgreSQL.
  3. Escribe código que reemplace la funcionalidad de los objetos de la base de datos y las funciones que no están disponibles en Cloud Spanner.

Migra datos

Después de crear tu base de datos de Cloud Spanner y de reestructurar tu código de aplicación, puedes migrar tus datos a Cloud Spanner.

  1. Usa el comando COPY de PostgreSQL para volcar datos a archivos .csv.
  2. Sube los archivos .csv a Cloud Storage.

    1. Crea un depósito de Cloud Storage.
    2. En la consola de Cloud Storage, haz clic en el nombre del depósito para abrir el navegador del depósito.
    3. Haz clic en Subir archivos.
    4. Navega al directorio que contiene los archivos .csv y selecciónalos.
    5. Haz clic en Abrir.
  3. Crea una aplicación para importar datos a Cloud Spanner. Esta aplicación podría usar Dataflow o podría usar las bibliotecas cliente directamente. Asegúrate de seguir las instrucciones en Prácticas recomendadas de carga de datos masivos para obtener el mejor rendimiento.

Prueba

Prueba todas las funciones de la aplicación contra la instancia de Cloud Spanner para verificar que funcionen como se espera. Ejecuta cargas de trabajo a nivel de producción para asegurarte de que el rendimiento cumpla con tus necesidades. Actualiza la cantidad de nodos según sea necesario para cumplir tus objetivos de rendimiento.

Pasa al nuevo sistema

Después de completar la prueba inicial de la aplicación, activa el nuevo sistema mediante uno de los siguientes procesos. La migración sin conexión es la forma más sencilla de migrar. Sin embargo, este enfoque hace que tu aplicación no esté disponible durante un período y no proporciona ninguna ruta de reversión si encuentras problemas de datos más adelante. Para realizar una migración sin conexión, sigue estos pasos:

  1. Borra todos los datos de la base de datos de Cloud Spanner.
  2. Cierra la aplicación que se orienta a la base de datos de PostgreSQL.
  3. Exporta todos los datos de la base de datos de PostgreSQL y, luego, impórtalos a la base de datos de Cloud Spanner como se describe en Migra datos.
  4. Inicia la aplicación que se orienta a la base de datos de Cloud Spanner.

    Dataflow de migración sin conexión

La migración en vivo es posible y requiere grandes cambios en tu aplicación para admitir la migración.

Ejemplos de migración de esquemas

En estos ejemplos, se muestran instrucciones CREATE TABLE para varias tablas en el esquema de la base de datos de PostgreSQL de MusicBrainz. En cada ejemplo, se incluye el esquema de PostgreSQL y el esquema de Cloud Spanner.

tabla artist_credit

Versión de 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()
);

Versión de 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);

tabla recording

Versión de 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
);

Versión de 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);

tabla recording-alias

Versión de 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
);

Versión de 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;