Migrar claves principales

En esta página se describe cómo migrar claves principales de las tablas de tu base de datos de origen a bases de datos de Spanner con dialecto GoogleSQL y con dialecto PostgreSQL. Antes de llevar a cabo los procedimientos de esta página, consulta la descripción general de la migración de claves principales.

Antes de empezar

  • Para obtener los permisos que necesitas para migrar claves principales a Spanner, pide a tu administrador que te conceda el rol de gestión de identidades y accesos Administrador de bases de datos de Cloud Spanner (roles/spanner.databaseAdmin) en la instancia.

Migrar claves secuenciales generadas automáticamente

Si vas a migrar desde una base de datos que usa claves monotónicas secuenciales, como AUTO_INCREMENT en MySQL, SERIAL en PostgreSQL o el tipo IDENTITY estándar en SQL Server u Oracle, ten en cuenta la siguiente estrategia de migración de alto nivel:

  1. En Spanner, replica la estructura de la tabla de tu base de datos de origen con una clave principal de tipo entero.
  2. En cada columna de Spanner que contenga valores secuenciales, crea una secuencia y asigna la función GET_NEXT_SEQUENCE_VALUE ( GoogleSQL, PostgreSQL) como valor predeterminado de la columna.
  3. Migrar los datos con las claves originales de la base de datos de origen a Spanner. Puedes usar la herramienta de migración de Spanner o una plantilla de Dataflow.
    1. También puedes establecer restricciones de clave externa para cualquier tabla dependiente.
  4. Antes de insertar datos nuevos, ajusta la secuencia de Spanner para omitir el intervalo de valores de clave existentes.
  5. Inserta datos nuevos y permite que la secuencia genere claves únicas automáticamente.

Flujo de trabajo de migración de ejemplo

El siguiente código define la estructura de la tabla y la secuencia relacionada en Spanner mediante un objeto SEQUENCE y establece el objeto como valor principal predeterminado de la tabla 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)
);

La opción bit_reversed_positive indica que los valores generados por la secuencia son del tipo INT64, son mayores que cero y no son secuenciales.

Cuando migras filas de tu base de datos de origen a Spanner, las claves principales no cambian.

En el caso de las inserciones nuevas que no especifican una clave principal, Spanner obtiene automáticamente un valor nuevo llamando a la función GET_NEXT_SEQUENCE_VALUE(GoogleSQL o PostgreSQL).

Estos valores se distribuyen de forma uniforme en el intervalo [1, 263] y puede haber colisiones con las claves existentes. Para evitarlo, puedes configurar la secuencia con ALTER_SEQUENCE (GoogleSQL o PostgreSQL) para omitir el intervalo de valores cubierto por las claves existentes.

Supongamos que la tabla singers se ha migrado desde PostgreSQL, donde su clave principal singer_id es de tipo SERIAL. A continuación, se muestra el DDL de la base de datos de origen de PostgreSQL:

PostgreSQL

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

Los valores de clave principal aumentan de forma monótona. Después de la migración, puede recuperar el valor máximo de la clave principal singer_id en Spanner. Usa el siguiente código en Spanner:

GoogleSQL

SELECT MAX(SingerId) FROM Singers;

PostgreSQL

SELECT MAX(SingerId) FROM Singers;

Supongamos que el valor devuelto es 20.000. Puedes configurar la secuencia de Spanner para que omita el intervalo [1, 21000]. Los 1000 adicionales sirven como margen para dar cabida a las escrituras en la base de datos de origen después de la migración inicial. Las claves nuevas generadas en Spanner no entran en conflicto con el intervalo de claves principales generadas en la base de datos PostgreSQL de origen. Usa el siguiente código en Spanner:

GoogleSQL

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

PostgreSQL

ALTER SEQUENCE SingerIdSequence SKIP RANGE 1 21000;

Usar Spanner y tu base de datos de origen

Puedes usar el concepto de intervalo de omisión para admitir situaciones en las que Spanner o tu base de datos de origen generen claves principales. Por ejemplo, puedes habilitar la replicación en ambas direcciones para la recuperación ante desastres durante un cambio de migración.

Para ello, ambas bases de datos generan claves principales y los datos se sincronizan entre ellas. Puede configurar cada base de datos para que cree claves principales en intervalos de claves no superpuestos. Cuando defines un intervalo para tu base de datos de origen, puedes configurar la secuencia de Spanner para que se salte ese intervalo.

Por ejemplo, después de migrar la aplicación de canciones, replica los datos de PostgreSQL a Spanner para reducir el tiempo necesario para cambiar.

Una vez que hayas actualizado y probado la aplicación en Spanner, puedes dejar de usar tu base de datos PostgreSQL de origen y usar Spanner, que se convertirá en el sistema de registro de las actualizaciones y las nuevas claves principales. Cuando Spanner tome el control, podrás invertir el flujo de datos entre las bases de datos en la instancia de PostgreSQL.

Supongamos que tu base de datos PostgreSQL de origen usa claves primarias SERIAL, que son números enteros de 32 bits con signo. Las claves principales de Spanner son números de 64 bits más grandes. En PostgreSQL, cambia la columna de clave principal a una columna de 64 bits o bigint. Usa el siguiente código en tu base de datos PostgreSQL de origen:

PostgreSQL

ALTER TABLE Singers ALTER COLUMN SingerId TYPE bigint;

Puede definir una restricción CHECK en la tabla de la base de datos PostgreSQL de origen para asegurarse de que los valores de la clave principal SingerId siempre sean menores o iguales que 231-1.

Usa el siguiente código en tu base de datos PostgreSQL de origen:

PostgreSQL

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

En Spanner, podemos modificar la secuencia para omitir el intervalo [1, 231-1].

Usa el siguiente código en 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;

Tu base de datos PostgreSQL de origen siempre genera claves en el espacio de números enteros de 32 bits, mientras que las claves de Spanner se limitan al espacio de números enteros de 64 bits, que es mayor que todos los valores de números enteros de 32 bits. De esta forma, ambas bases de datos pueden generar de forma independiente claves principales que no entren en conflicto.

Migrar columnas de clave UUID

Las claves UUIDv4 son únicas, independientemente de dónde se generen. Las claves UUID generadas en otro lugar se integran con las nuevas claves UUID generadas en Spanner.

Para migrar claves UUID a Spanner, sigue esta estrategia general:

  1. Define tus claves UUID en Spanner mediante columnas de cadena con una expresión predeterminada. Usa la función GENERATE_UUID() (GoogleSQL, PostgreSQL).
  2. Exporta los datos del sistema de origen y serializa las claves UUID como cadenas.
  3. Importa las claves principales en Spanner.
  4. Opcional: Habilita las claves externas.

A continuación, se muestra un ejemplo de flujo de trabajo de migración:

En Spanner, define una columna de clave principal UUID como tipo STRING o TEXT y asigna GENERATE_UUID() (GoogleSQL o PostgreSQL) como valor predeterminado. Migra todos los datos de tu base de datos de origen a Spanner. Después de la migración, a medida que se insertan nuevas filas, Spanner llama a GENERATE_UUID() para generar nuevos valores UUID para las claves principales. Por ejemplo, la clave principal FanClubId obtiene un valor UUIDv4 cuando se inserta una fila nueva en la tabla FanClubs. Usa el siguiente código en 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 tus propias claves principales

Es posible que tu aplicación dependa del orden de la clave principal para determinar la antigüedad de los datos o para secuenciar los datos recién creados. Para usar claves secuenciales generadas externamente en Spanner, puedes crear una clave compuesta que combine un valor distribuido de forma uniforme, como un hash, como primer componente y tu clave secuencial como segundo componente. De esta forma, puedes conservar los valores de clave secuenciales sin crear puntos de acceso a gran escala. Ten en cuenta el siguiente flujo de trabajo de migración:

Supongamos que tienes que migrar a Spanner una tabla de MySQL students con una clave principal AUTO_INCREMENT. Usa el siguiente código en tu base de datos MySQL de origen:

MySQL

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

En Spanner, puede añadir una columna generada StudentIdHash creando un hash de la columna StudentId. Por ejemplo:

StudentIdHash = FARM_FINGERPRINT(CAST(StudentId AS STRING))

Puedes usar el siguiente código en 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 columnas de clave secuencial

Si tu sistema de base de datos de origen genera valores secuenciales para una columna de clave, puedes usar una secuencia positiva invertida por bits (GoogleSQL o PostgreSQL) en tu esquema de Spanner para generar valores que se distribuyan de forma uniforme en el espacio de números enteros positivos de 64 bits. Para evitar que la secuencia de Spanner genere un valor que se solape con un valor migrado, puedes definir un intervalo omitido.

Por ejemplo, puede omitir el intervalo de 1 a 4.294.967.296 (2^32) en las dos secuencias siguientes si sabe que la base de datos de origen solo genera números enteros 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;

Si usas IDENTITY columnas para generar automáticamente valores enteros para tus columnas clave, puedes definir skip ranges:

GoogleSQL

Para definir un intervalo de omisión, usa el 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 un intervalo de omisión, usa el 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 columnas de clave invertidas por bits

Si ya has invertido los bits de los valores de clave para evitar problemas de puntos calientes en tu base de datos de origen, también puedes usar una secuencia positiva invertida por bits de Spanner (GoogleSQL, PostgreSQL) para seguir generando esos valores. Para evitar que se generen valores duplicados, puedes configurar la secuencia para que empiece a contar a partir de un número personalizado.

Por ejemplo, si inviertes los números del 1 al 1000 para generar valores de clave principal, la secuencia de Spanner puede iniciar su contador desde cualquier número superior a 10.000. Opcionalmente, puede elegir un número alto para dejar un espacio para las nuevas escrituras que se produzcan en la base de datos de origen después de la migración de datos. En el siguiente ejemplo, los contadores empiezan en 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 usas IDENTITY columnas para generar automáticamente valores enteros para tus columnas clave, puedes definir un contador inicial:

GoogleSQL

Para definir un contador inicial, usa el 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 un contador inicial, usa el 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;

Siguientes pasos