本頁面說明如何將主鍵從來源資料庫資料表遷移至 Spanner GoogleSQL 方言資料庫和 PostgreSQL 方言資料庫。在頁面上執行程序前,請先詳閱「主鍵遷移總覽」。
事前準備
-
如要取得將主鍵遷移至 Spanner 所需的權限,請要求管理員為您授予執行個體的 Cloud Spanner 資料庫管理員 (
roles/spanner.databaseAdmin
) IAM 角色。
遷移自動產生的連續金鑰
如果您要從使用序列單調鍵的資料庫進行遷移,例如 MySQL 中的 AUTO_INCREMENT
、PostgreSQL 中的 SERIAL
,或是 SQL Server 或 Oracle 中的標準 IDENTITY
類型,請考慮採用下列高層次遷移策略:
- 在 Spanner 中,使用整數主鍵複製來源資料庫的資料表結構。
- 針對 Spanner 中包含序列值的每個資料欄,建立序列並指派
GET_NEXT_SEQUENCE_VALUE
( GoogleSQL、PostgreSQL) 函式做為資料欄的預設值。 - 將含有原始索引鍵的現有資料從來源資料庫遷移至 Spanner。建議您使用 Spanner 遷移工具或
資料流範本。
- 您可以選擇為任何依附資料表建立外鍵限制。
- 插入新資料前,請調整 Spanner 序列,略過現有鍵值的範圍。
- 插入新資料,讓序列自動產生不重複的鍵。
遷移工作流程範例
以下程式碼使用 SEQUENCE
物件,在 Spanner 中定義資料表結構和相關序列,並將該物件設為目標資料表的預設主要值:
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 時,主鍵會保持不變。
如果新插入的資料未指定主鍵,Spanner 會透過呼叫 GET_NEXT_SEQUENCE_VALUE
(GoogleSQL 或 PostgreSQL) 函式,自動擷取新值。
這些值會平均分佈在 [1, 263]
範圍內,且可能與現有鍵發生衝突。為避免這種情況,您可以使用 ALTER_SEQUENCE
(GoogleSQL 或 PostgreSQL) 設定序列,跳過現有鍵涵蓋的值範圍。
假設 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 或來源資料庫產生主鍵的情況,例如在遷移切換期間,為災難復原目的啟用任一方向的複製作業。
為支援這項功能,兩個資料庫都會產生主鍵,並同步處理兩者之間的資料。您可以設定每個資料庫,在不重疊的鍵範圍內建立主鍵。為來源資料庫定義範圍時,您可以設定 Spanner 序列略過該範圍。
舉例來說,在音樂曲目應用程式遷移完成後,請將資料從 PostgreSQL 複製到 Spanner,以縮短切換所需的時間。
在 Spanner 上更新及測試應用程式後,您可以停止使用來源 PostgreSQL 資料庫,改用 Spanner,讓 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 鍵整合。
請考慮採用下列高層策略,將 UUID 鍵遷移至 Spanner:
- 使用含有預設運算式的字串資料欄,在 Spanner 中定義 UUID 鍵。使用
GENERATE_UUID()
函式 (GoogleSQL、PostgreSQL)。 - 從來源系統匯出資料,並將 UUID 鍵序列化為字串。
- 將主鍵匯入 Spanner。
- 選用:啟用外鍵。
以下是遷移工作流程範例:
在 Spanner 中,將 UUID 主鍵欄定義為 STRING
或 TEXT
類型,並將 GENERATE_UUID()
(GoogleSQL 或 PostgreSQL) 指派為其預設值。將所有資料從來源資料庫遷移至 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');
遷移自己的主鍵
應用程式可能會依據主鍵順序判斷資料的最新狀態,或為新建立的資料排序。如要在 Spanner 中使用外部產生的順序鍵,您可以建立複合鍵,將均勻分布的值 (例如雜湊值) 做為第一個元件,並將順序鍵做為第二個元件。這樣一來,您就能保留順序鍵值,而不會大規模建立熱點。請考慮下列遷移工作流程:
假設您需要將具有 AUTO_INCREMENT
主鍵的 MySQL 資料表 students
遷移至 Spanner。在來源 MySQL 資料庫中使用以下程式碼:
MySQL
CREATE TABLE Students ( StudentId INT NOT NULL AUTO_INCREMENT, Info VARCHAR(2048), PRIMARY KEY (StudentId) );
在 Spanner 中,您可以建立 StudentId
欄的雜湊,藉此新增產生的資料欄 StudentIdHash
。例如:
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) );
遷移序列索引鍵欄
如果來源資料庫系統會為關鍵欄產生序列值,您可以在 Spanner 結構定義中使用位元反轉的正序序列 (GoogleSQL、PostgreSQL),產生在正 64 位元整數數字空間中平均分配的值。為避免 Spanner 序列產生的值與遷移的值重疊,您可以為該序列定義略過的範圍。
舉例來說,如果您知道來源資料庫只會產生 32 位元整數,則可以略過下列兩個序列的 1 到 4,294,967,296 (2^32) 範圍:
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;
如果您使用 IDENTITY
資料欄自動產生主要欄的整數值,可以設定略過範圍:
GoogleSQL
如要設定略過範圍,請使用 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
如要設定略過範圍,請使用 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;
遷移位元反轉的索引鍵欄
如果您已將索引鍵值反向位元,以避免來源資料庫出現熱點問題,也可以使用 Spanner 反向位元正序序列 (GoogleSQL、PostgreSQL) 繼續產生這類值。為避免產生重複值,您可以將序列設為從自訂編號開始計數。
舉例來說,如果您將 1 到 1000 的數字倒轉,產生主鍵值,Spanner 序列可以從任何大於 10,000 的數字開始計數。您可以選擇較高的數字,為資料遷移後在來源資料庫中發生的新寫入作業保留緩衝區。在下列範例中,計數器會從 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;
如果您使用 IDENTITY
欄自動產生主要欄的整數值,可以設定起始計數器:
GoogleSQL
如要設定起始計數器,請使用 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
如要設定起始計數器,請使用 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;