PolarDB PostgreSQL版(以下简称 PolarDB-PG)是一款阿里云自主研发的企业级数据库产品,采用计算存储分离架构,兼容 PostgreSQL 与 Oracle。PolarDB-PG 的存储与计算能力均可横向扩展,具有高可靠、高可用、弹性扩展等企业级数据库特性。同时,PolarDB-PG 具有大规模并行计算能力,可以应对 OLTP 与 OLAP 混合负载;还具有时空、向量、搜索、图谱等多模创新特性,可以满足企业对数据处理日新月异的新需求。
介绍
Sequence 作为数据库中的一个特别的表级对象,可以根据用户设定的不同属性,产生一系列有规则的整数,从而起到发号器的作用。
在使用方面,可以设置永不重复的 Sequence 用来作为一张表的主键,也可以通过不同表共享同一个 Sequence 来记录多个表的总插入行数。根据 ANSI 标准,一个 Sequence 对象在数据库要具备以下特征:
- 独立的数据库对象 (CREATE SEQUENCE),和表、视图同一层级
- 可以设置生成属性:初始值 (star value),步长 (increment),最大/小值 (max/min),循环产生 (cycle),缓存 (cache)等
- Sequence 对象在当前值的基础上进行递增或者递减,当前值被初始化为初始值
- 在设置循环后,当前值的变化具有周期性;不设置循环下,当前值的变化具有单调性,当前值到达最值后不可再变化
为了解释上述特性,我们分别定义 a
、b
两种序列来举例其具体的行为。
CREATE SEQUENCE a start with 5 minvalue -1 increment -2;
CREATE SEQUENCE b start with 2 minvalue 1 maxvalue 4 cycle;
复制
两个 Sequence 对象提供的序列值,随着序列申请次数的变化,如下所示:
PostgreSQL | Oracle | SQLSERVER | MySQL | MariaDB | DB2 | Sybase | Hive |
---|---|---|---|---|---|---|---|
支持 | 支持 | 支持 | 仅支持自增字段 | 支持 | 支持 | 仅支持自增字段 | 不支持 |
为了更进一步了解 PostgreSQL 中的 Sequence 对象,我们先来了解 Sequence 的用法,并从用法中透析 Sequence 背后的设计原理。
使用方法
PostgreSQL 提供了丰富的 Sequence 调用接口,以及组合使用的场景,以充分支持开发者的各种需求。
SQL 接口
PostgreSQL 对 Sequence 对象也提供了类似于 表 的访问方式,即 DQL、DML 以及 DDL。我们从下图中可一览对外提供的 SQL 接口。
分别来介绍以下这几个接口:
currval
该接口的含义为,返回 Session 上次使用的某一 Sequence 的值。
postgres=# select nextval('seq');
nextval
---------
2
(1 row)
postgres=# select currval('seq');
currval
---------
2
(1 row)
复制
需要注意的是,使用该接口必须使用过一次 nextval
方法,否则会提示目标 Sequence 在当前 Session 未定义。
postgres=# select currval('seq');
ERROR: currval of sequence "seq" is not yet defined in this session
复制
lastval
该接口的含义为,返回 Session 上次使用的 Sequence 的值。
postgres=# select nextval('seq');
nextval
---------
3
(1 row)
postgres=# select lastval();
lastval
---------
3
(1 row)
复制
同样,为了知道上次用的是哪个 Sequence 对象,需要用一次 nextval('seq')
,让 Session 以全局变量的形式记录下上次使用的 Sequence 对象。
lastval
与 curval
两个接口仅仅只是参数不同,currval
需要指定是哪个访问过的 Sequence 对象,而 lastval
无法指定,只能是最近一次使用的 Sequence 对象。
nextval
该接口的含义为,取 Sequence 对象的下一个序列值。
通过使用 nextval
方法,可以让数据库基于 Sequence 对象的当前值,返回一个递增了 increment
数量的一个序列值,并将递增后的值作为 Sequence 对象当前值。
postgres=# CREATE SEQUENCE seq start with 1 increment 2;
CREATE SEQUENCE
postgres=# select nextval('seq');
nextval
---------
1
(1 row)
postgres=# select nextval('seq');
nextval
---------
3
(1 row)
复制
increment
称作 Sequence 对象的步长,Sequence 的每次以 nextval
的方式进行申请,都是以步长为单位进行申请的。同时,需要注意的是,Sequence 对象创建好以后,第一次申请获得的值,是 start value 所定义的值。对于 start value 的默认值,有以下 PostgreSQL 规则:
另外,nextval
是一种特殊的 DML,其不受事务所保护,即:申请出的序列值不会再回滚。
postgres=# BEGIN;
BEGIN
postgres=# select nextval('seq');
nextval
---------
1
(1 row)
postgres=# ROLLBACK;
ROLLBACK
postgres=# select nextval('seq');
nextval
---------
2
(1 row)
复制
PostgreSQL 为了 Sequence 对象可以获得较好的并发性能,并没有采用多版本的方式来更新 Sequence 对象,而是采用了原地修改的方式完成 Sequence 对象的更新,这种不用事务保护的方式几乎成为所有支持 Sequence 对象的 RDMS 的通用做法,这也使得 Sequence 成为一种特殊的表级对象。