暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PolarDB-PG原理解读——Sequence 使用、原理全面解析(一)

PolarDB农夫山泉 2023-08-29
196

PolarDB PostgreSQL版(以下简称 PolarDB-PG)是一款阿里云自主研发的企业级数据库产品,采用计算存储分离架构,兼容 PostgreSQL 与 Oracle。PolarDB-PG 的存储与计算能力均可横向扩展,具有高可靠、高可用、弹性扩展等企业级数据库特性。同时,PolarDB-PG 具有大规模并行计算能力,可以应对 OLTP 与 OLAP 混合负载;还具有时空、向量、搜索、图谱等多模创新特性,可以满足企业对数据处理日新月异的新需求。

介绍

Sequence 作为数据库中的一个特别的表级对象,可以根据用户设定的不同属性,产生一系列有规则的整数,从而起到发号器的作用。

在使用方面,可以设置永不重复的 Sequence 用来作为一张表的主键,也可以通过不同表共享同一个 Sequence 来记录多个表的总插入行数。根据 ANSI 标准,一个 Sequence 对象在数据库要具备以下特征:

  1. 独立的数据库对象 (CREATE SEQUENCE),和表、视图同一层级
  2. 可以设置生成属性:初始值 (star value),步长 (increment),最大/小值 (max/min),循环产生 (cycle),缓存 (cache)等
  3. Sequence 对象在当前值的基础上进行递增或者递减,当前值被初始化为初始值
  4. 在设置循环后,当前值的变化具有周期性;不设置循环下,当前值的变化具有单调性,当前值到达最值后不可再变化

为了解释上述特性,我们分别定义 ab 两种序列来举例其具体的行为。

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 接口。

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 对象。

lastvalcurval 两个接口仅仅只是参数不同,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 规则:

start_value=1,if:increment>0;start\_value = 1, if:increment > 0;

start_value=1,if:increment<0;start\_value = -1,if:increment < 0;

另外,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 成为一种特殊的表级对象。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论