在資料庫設計中,為表的每一行產生一個唯一識別碼是常見需求,類似於MySQL中的AUTO_INCREMENT。在PolarDB PostgreSQL分布式版中,這一功能通過序列(Sequence)對象實現,您可以通過SERIAL或BIGSERIAL等類型便捷地使用。然而,在分布式環境中,確保所有節點產生的ID全域唯一是一項挑戰。PolarDB為此提供了不同的實現機制,其行為和限制根據您選擇的序列類型(主要是其整數大小)而異。
序列類型差異
在為分布式表選擇序列類型之前,請首先通過下表瞭解它們的核心區別,以做出正確的技術選型。
特性 | 64位序列 ( | 16位/32位序列 ( |
推薦用法 | 強烈推薦用於所有分布式表。 | 不推薦用於分布式表,除非您能接受其限制。 |
實現原理 | 分布式產生:ID由 | 中心化產生:ID產生請求必須路由到主計算節點(主CN)。 |
ID產生 | - 可在任意計算節點(CN)上產生。 - 全域唯一,但不保證連續。 | - 只能在主CN上產生。 - 在主CN上產生時是連續的。 |
核心限制 | 產生的ID值會因來源節點不同而出現大的跳躍。 | 在主CN以外的任何節點上嘗試產生ID都會直接報錯。 |
詳細行為與樣本
64位序列
這是為分布式表產生唯一ID的推薦方式。
工作原理
為了在所有節點上都能安全地產生ID,PolarDB PostgreSQL分布式版將64位的整數空間進行切分:高16位用於嵌入當前節點的唯一ID,低48位用於在該節點上遞增的序列值。這種結構從根本上保證了不同節點產生的ID絕不會衝突。
行為分析
優點:您可以在任何一個計算節點(主CN或從CN)上執行
INSERT操作,具備高可用性和高吞吐能力。注意事項:由於ID中包含了節點資訊,從不同節點插入資料會導致ID值出現大幅跳躍,它們在數值上不是連續的。
樣本
-- 建立使用BIGSERIAL的分布式表
CREATE TABLE student (id BIGSERIAL, name TEXT);
SELECT create_distributed_table('student', 'id');
-- (串連到主CN) 插入兩條資料
INSERT INTO student (name) VALUES ('Alice'); -- id: 1
INSERT INTO student (name) VALUES ('Bob'); -- id: 2 (連續)
-- (切換串連到從CN) 再插入一條資料
INSERT INTO student (name) VALUES ('Charlie'); -- id: 281474976710657 (發生跳躍)
-- 查看結果
=> SELECT * FROM student ORDER BY id;
id | name
-------------------+---------
1 | Alice
2 | Bob
281474976710657 | Charlie
(3 rows)ID 281474976710657看起來是一個巨大的數字,其二進位表示揭示了其結構:0000000000000001 (節點ID) + 000...0001(序列值),含義為1號節點產生的第1個ID。
16位/32位序列
由於整數空間有限,這些類型無法嵌入節點ID來實現分布式產生。因此,它們採用了一種中心化產生的策略。
工作原理
為了保證全域唯一性,所有針對32/16位序列的ID產生請求都需被路由到主計算節點(主CN)上處理。
行為分析
優點:在主CN上產生的ID是連續的,符合單機資料庫的使用習慣。
使用限制:不可在主CN以外的任何節點(如從CN或DN)上執行會觸發ID產生的
INSERT操作,否則將導致報錯operation is not allowed on this node。
樣本
-- 建立使用SERIAL的分布式表
CREATE TABLE animal (id SERIAL, name TEXT);
SELECT create_distributed_table('animal', 'id');
-- (串連到主CN) 插入資料,操作成功
INSERT INTO animal (name) VALUES ('cat'); -- id: 1
SELECT * FROM animal;
id | name
----+------
1 | cat
(1 row)
-- (切換串連到從CN) 嘗試插入資料,操作失敗
INSERT INTO animal (name) VALUES ('dog');
ERROR: nextval(sequence) calls in worker nodes are not supported for column defaults of type int or smallint
HINT: If the command was issued from a worker node, try issuing it from the coordinator node instead.錯誤資訊明確指出,在工作節點(此處指從CN)上不支援為int或smallint類型的列調用nextval(即產生序列值)。
總結與最佳實務
首選
BIGSERIAL:在為分布式表設計自增ID時,應始終優先選擇BIGSERIAL或基於BIGINT的IDENTITY列。接受ID不連續:使用
BIGSERIAL時,商務邏輯不應依賴於ID的嚴格連續性。ID的唯一性和單調遞增性(在單個節點內)是可以保證的。謹慎使用
SERIAL:僅當您的業務情境可以完全容忍所有寫操作都通過主CN進行,且不關心從CN的寫入可用性時,才可考慮使用SERIAL或SMALLSERIAL。