全部产品
Search
文档中心

云原生数据库 PolarDB:分布式Sequence的使用及限制

更新时间:Sep 16, 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