PolarDB for PostgreSQL 序列(Sequence)技术深度解析
【免费下载链接】PolarDB-for-PostgreSQL 项目地址: https://gitcode.com/gh_mirrors/pol/PolarDB-for-PostgreSQL
引言
在数据库系统中,序列(Sequence)是一种非常重要的对象,它为应用程序提供了高效、可靠的唯一值生成机制。本文将深入探讨 PolarDB for PostgreSQL 中的序列技术实现原理,帮助开发者更好地理解和使用这一功能。
序列基础概念
什么是序列
序列是数据库中的一个特殊对象,它能够按照预定义的规则生成一系列有序的数字。这些数字通常用于:
- 作为表的主键值
- 生成唯一的订单号或交易号
- 实现多表共享的计数器功能
序列的核心特性
根据 ANSI SQL 标准,序列应当具备以下特性:
- 作为独立数据库对象存在(与表、视图同级别)
- 可配置多种生成属性:初始值、步长、最大值/最小值、循环模式、缓存大小等
- 基于当前值进行递增或递减
- 循环模式下具有周期性,非循环模式下具有单调性
序列的使用方法
基本SQL接口
PolarDB for PostgreSQL 提供了丰富的序列操作接口:
-
nextval - 获取序列的下一个值
SELECT nextval('my_sequence'); -
currval - 获取当前会话中最近使用的序列值
SELECT currval('my_sequence'); -
lastval - 获取当前会话中最近使用的任意序列值
SELECT lastval(); -
setval - 设置序列的当前值
SELECT setval('my_sequence', 100);
序列创建与修改
创建序列的基本语法:
CREATE SEQUENCE seq_name
[INCREMENT BY increment]
[MINVALUE minvalue | NO MINVALUE]
[MAXVALUE maxvalue | NO MAXVALUE]
[START WITH start]
[CACHE cache]
[CYCLE | NO CYCLE];
修改序列的语法:
ALTER SEQUENCE seq_name
[INCREMENT BY increment]
[MINVALUE minvalue | NO MINVALUE]
[MAXVALUE maxvalue | NO MAXVALUE]
[RESTART [WITH restart]]
[CACHE cache]
[CYCLE | NO CYCLE];
序列的典型应用场景
-
显式调用 - 直接在SQL语句中使用
INSERT INTO users (id, name) VALUES (nextval('user_id_seq'), '张三'); -
默认值约束 - 作为列的默认值
CREATE TABLE users ( id BIGINT DEFAULT nextval('user_id_seq'), name VARCHAR(100) ); -
SERIAL类型 - 简化自增列创建
CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(100) ); -
IDENTITY列 - PostgreSQL 10+引入的标准语法
CREATE TABLE users ( id INT GENERATED ALWAYS AS IDENTITY, name VARCHAR(100) );
序列的实现原理
序列的存储结构
PolarDB for PostgreSQL 中序列的实现包含两部分:
-
系统表pg_sequence - 存储序列的元数据信息
CREATE TABLE pg_sequence ( seqrelid OID NOT NULL, -- 序列关系的OID seqtypid OID NOT NULL, -- 序列数据类型 seqstart BIGINT NOT NULL, -- 起始值 seqincrement BIGINT NOT NULL, -- 增量 seqmax BIGINT NOT NULL, -- 最大值 seqmin BIGINT NOT NULL, -- 最小值 seqcache BIGINT NOT NULL, -- 缓存大小 seqcycle BOOLEAN NOT NULL -- 是否循环 ); -
序列数据表 - 存储序列的当前状态
typedef struct { int64 last_value; // 当前序列值 int64 log_cnt; // WAL日志计数 bool is_called; // 是否已被调用 } FormData_pg_sequence_data;
序列值生成机制
序列值的生成过程遵循以下规则:
-
当调用
nextval时,系统首先检查会话缓存中是否有可用的序列值 -
如果缓存耗尽,则:
- 获取序列数据表的排他锁
- 更新
last_value字段 - 计算新的缓存范围
- 释放锁
-
WAL日志优化:
- 不是每次
nextval都写WAL - 使用
log_cnt字段记录预申请的序列值数量 - 默认预申请32个值(SEQ_LOG_VALS)
- 不是每次
缓存机制
为了提高并发性能,PolarDB for PostgreSQL 实现了序列会话缓存:
- 每个会话维护自己的序列值缓存
- 缓存大小由
CACHE参数指定 - 只有当缓存耗尽时才需要访问序列数据表
缓存数据结构:
typedef struct {
Oid relid; // 序列OID
int64 last; // 最后返回的值
int64 cached; // 已缓存的最后一个值
int64 increment; // 增量值
} SeqTableData;
性能优化建议
-
合理设置CACHE大小:
- 高并发场景下增大CACHE值
- 但过大的CACHE可能导致序列值不连续
-
选择合适的序列类型:
- 根据需求范围选择smallint/int/bigint
- 避免不必要的空间浪费
-
避免频繁创建/删除序列:
- 序列创建有一定开销
- 考虑重用现有序列
常见问题解答
Q: 为什么序列值在事务回滚后不回滚?
A: 这是设计使然。序列值生成不受事务保护,以保证高性能和唯一性。如果需要事务保护的值,应考虑其他方案。
Q: 序列值会出现空洞吗?
A: 会的。在以下情况可能出现空洞:
- 事务回滚
- 系统崩溃
- 使用CACHE参数
Q: 如何重置序列?
A: 可以使用:
ALTER SEQUENCE seq_name RESTART WITH 1;
或者
SELECT setval('seq_name', 1, false);
总结
PolarDB for PostgreSQL 的序列实现提供了高性能、高可用的唯一值生成方案。通过理解其内部实现机制,开发者可以更好地利用这一功能,设计出更高效的数据库应用。序列的缓存机制和WAL优化使其在高并发场景下仍能保持良好的性能表现。
在实际应用中,应根据具体场景选择合适的序列使用方式,并合理配置相关参数,以达到最佳的性能和功能平衡。
【免费下载链接】PolarDB-for-PostgreSQL 项目地址: https://gitcode.com/gh_mirrors/pol/PolarDB-for-PostgreSQL
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



