全部產品
Search
文件中心

PolarDB:分布式Sequence的使用及限制

更新時間:Sep 17, 2025

在資料庫設計中,為表的每一行產生一個唯一識別碼是常見需求,類似於MySQL中的AUTO_INCREMENT。在PolarDB PostgreSQL分布式版中,這一功能通過序列(Sequence)對象實現,您可以通過SERIALBIGSERIAL等類型便捷地使用。然而,在分布式環境中,確保所有節點產生的ID全域唯一是一項挑戰。PolarDB為此提供了不同的實現機制,其行為和限制根據您選擇的序列類型(主要是其整數大小)而異。

序列類型差異

在為分布式表選擇序列類型之前,請首先通過下表瞭解它們的核心區別,以做出正確的技術選型。

特性

64位序列 (BIGSERIAL)

16位/32位序列 (SERIALSMALLSERIAL)

推薦用法

強烈推薦用於所有分布式表。

不推薦用於分布式表,除非您能接受其限制。

實現原理

分布式產生:ID由節點ID(16位)+序列值(48位)組成。

中心化產生: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)上不支援為intsmallint類型的列調用nextval(即產生序列值)。

總結與最佳實務

  1. 首選BIGSERIAL:在為分布式表設計自增ID時,應始終優先選擇BIGSERIAL或基於BIGINTIDENTITY列。

  2. 接受ID不連續:使用BIGSERIAL時,商務邏輯不應依賴於ID的嚴格連續性。ID的唯一性和單調遞增性(在單個節點內)是可以保證的。

  3. 謹慎使用SERIAL:僅當您的業務情境可以完全容忍所有寫操作都通過主CN進行,且不關心從CN的寫入可用性時,才可考慮使用SERIALSMALLSERIAL