迁移主键

本文档提供了从哪个位置迁移主键的说明 将源数据库表复制到 Spanner。您必须熟悉 此处提供的信息 主键迁移概览

准备工作

  • 如需获取将主键迁移到 Spanner 所需的权限, 请让管理员授予您 实例上的 Cloud Spanner Database Admin (roles/spanner.databaseAdmin) IAM 角色。

    <ph type="x-smartling-placeholder">

迁移自动生成的序列键

如果要从使用顺序单调键的数据库进行迁移, 例如 AUTO_INCREMENT 在 MySQL 中,SERIAL 或者 SQL Server 或 Oracle 中的标准 IDENTITY 类型。 请考虑采用以下总体迁移策略:

  1. 在 Spanner 中,从 您的源数据库(使用整数主键)。
  2. 对于 Spanner 中包含顺序值的每一列, 创建一个序列并分配 GET_NEXT_SEQUENCE_VALUEGoogleSQLPostgreSQL) 函数作为列的默认值。
  3. 使用原始密钥从来源迁移现有数据 数据库导入 Spanner。您可以考虑使用 Spanner 迁移工具Dataflow 模板
  4. 您还可以选择创建 外键约束 依赖表
  5. 在插入新数据之前,请调整 Spanner 序列,以跳过现有键值对的范围。
  6. 插入新数据,使序列能够自动生成唯一键。

迁移工作流示例

以下代码定义了 使用 SEQUENCE 对象,并设置该对象 用作目标表的默认主值:

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

bit_reversed_positive 选项表示 序列的类型为 INT64、大于零,并且不依序。

将现有行从源数据库迁移到 则主键保持不变。

对于未指定主键的新插入,Spanner 调用该方法来自动检索新值, GET_NEXT_SEQUENCE_VALUE()(GoogleSQLPostgreSQL) 函数。

这些值在 [1, 263] 范围内均匀分布, 可能会与现有密钥发生冲突。为防止出现这种情况,您可以 使用 ALTER_SEQUENCEGoogleSQLPostgreSQL)配置序列,以跳过 现有键覆盖的值。

假设 singers 表是从 PostgreSQL 迁移而来,该表的主键为 singer_id 的类型为 SERIAL。以下 PostgreSQL 显示了您的源数据库 DDL:

PostgreSQL

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

主键值单调递增。迁移后 您可以在 Spanner 上检索主键 singer_id 的最大值。 在 Spanner 中使用以下代码:

GoogleSQL

SELECT MAX(SingerId) FROM Singers;

PostgreSQL

SELECT MAX(SingerId) FROM Singers;

假设返回值为 20,000。你可以配置 Spanner 序列来跳过 [1, 21000] 范围。额外添加的 1,000 个 缓冲区,以适应初始迁移后对源数据库的写入。 在 Spanner 中生成的新键与 源 PostgreSQL 数据库中生成的主键。 在 Spanner 中使用以下代码:

GoogleSQL

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

PostgreSQL

ALTER SEQUENCE SingerIdSequence SKIP RANGE 1 21000;

使用 Spanner 和源数据库

您可以使用跳过范围概念来支持以下场景: 或者,您的源数据库会生成主键,例如,要在 迁移割接期间的灾难恢复方向。

为了支持这一点,两个数据库都会生成主键,数据 会在它们之间同步您可以将每个数据库配置为 键的范围不同。定义来源范围时 您可以配置 Spanner 序列以跳过该数据库, 范围。

例如,在迁移音乐曲目应用后,请复制 将数据从 PostgreSQL 传输到 Spanner, 切换。

在 Spanner 上更新并测试应用后,您可以 停止使用源 PostgreSQL 数据库并使用 Spanner, 使其成为更新和新主键的记录系统。 Spanner 接管后,您可以将流程逆转 将数据整合到 PostgreSQL 实例中。

假设您的源 PostgreSQL 数据库使用 SERIAL 主键,它们是 32 位有符号整数。Spanner 主键为 64 位更大 数字。在 PostgreSQL 中,将主键列更改为 64 位列, 或 bigint。在源 PostgreSQL 数据库中使用以下代码:

PostgreSQL

ALTER TABLE Singers ALTER COLUMN SingerId TYPE bigint;

您可以为源 PostgreSQL 数据库中的表设置 CHECK 限制条件 ,以确保 SingerId 主键的值始终小于或 等于 231-1。 在源 PostgreSQL 数据库中使用以下代码:

PostgreSQL

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

在 Spanner 中,我们可以更改序列以跳过 [1, 231-1] 范围。 在 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;

源 PostgreSQL 数据库始终生成 32 位整数的密钥 空间,而 Spanner 键被限制为 64 位整数 大于所有 32 位整数值。这样可以确保 数据库可以独立生成不冲突的主键。

迁移 UUID 键列

无论 UUIDv4 密钥是在何处生成的,它们实际上都是唯一的。 在其他位置生成的 UUID 密钥与 Spanner。

请考虑以下总体迁移策略 使用 UUID 键导入 Spanner:

  1. 在 Spanner 中使用包含 默认表达式。使用 GENERATE_UUID() 函数(GoogleSQLPostgreSQL)。
  2. 从源系统导出数据,将 UUID 键序列化为字符串。
  3. 将主键导入 Spanner。
  4. 可选:启用外键。

以下是一个迁移工作流示例:

在 Spanner 中,将 UUID 主键列定义为 STRING,或 TEXT 类型,并将 GENERATE_UUID()GoogleSQLPostgreSQL)指定为默认值。将所有 将数据从源数据库传输到 Spanner。迁移后, 将插入新行,Spanner 会调用 GENERATE_UUID() 以 为主键生成新的 UUID 值。例如,主键 在表 FanClubs 中插入新行时,FanClubId 会获取 UUIDv4 值。 在 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');

迁移您自己的主键

您的应用程序可能会依靠主键顺序来确定 data 为 或 ,则会对新创建的数据进行排序。要使用外部生成的 顺序键,则可以创建复合键 该方法将均匀分布的值(例如哈希值)组合起来,作为第一个 组件,并将顺序键用作第二个组件。这样, 则可以保留顺序键值,而不会大规模创建热点。 请考虑以下迁移工作流:

假设您需要迁移一个 MySQL 表 students,该表为 分配给 Spanner 的 AUTO_INCREMENT 主键。 在源 MySQL 数据库中使用以下代码:

MySQL

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

在 Spanner 中,您可以通过创建以下内容的哈希值来添加生成的列 StudentIdHash StudentId 列。 例如:

  StudentIdHash = FARM_FINGERPRINT(CAST(StudentId AS STRING))

您可以在 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)
);

后续步骤