lightdb/postgresql中序列的使用以及oracle兼容计划

一、postgresql中的序列

1.1 场景需求

需要向下图一样,需要对产品编码编码设置一个序列。编码规则 SKU + 序列号:

1.2 序列

序列是基于bigint算法的,因此范围是不能超过一个八字节 整数的范围(-9223372036854775808 到 9223372036854775807)。

由于nextval和setval调用绝不会回滚, 如果需要序数的"无间隙"分配,则不能使用序列对象。可以 通过在一个只包含一个计数器的表上使用排他锁来构建无间隙的分配, 但是这种方案比序列对象开销更大,特别是当有很多事务并发请求序数时

创建和使用语法:

1
2
3
4
5
CREATE SEQUENCE serial START 101;
SELECT nextval('serial');
 nextval
---------
 101

本节描述用于操作序列对象的函数,序列对象也被称为序列生成器或者就是序列。

序列对象都是用CREATE SEQUENCE创建的特殊的单行表。

序列对象通常用于为表的行生成唯一的标识符。

表 中列出的这些序列函数,可以为我们从序列对象中获取连续的序列值提供了简单的、多用户安全的 方法。

获取序列值是安全的,可以用来和其他键组合形成唯一主键。

补充:PostgreSQL中序列相关函数 nextval、currval、lastval、setval、setval

PostgreSQL中序列主要涉及到的函数是

函数 返回类型 描述
nextval(regclass) bigint 递增序列对象到它的下一个数值并且返回该值。这个动作是自动完成的。即使多个会话并发运行nextval,每个进程也会安全地收到一个唯一的序列值。
currval(regclass) bigint 在当前会话中返回最近一次nextval抓到的该序列的数值。(如果在本会话中从未在该序列上调用过 nextval,那么会报告一个错误。)请注意因为此函数返回一个会话范围的数值,而且也能给出一个可预计的结果,因此可以用于判断其它会话是否执行过nextval。
lastval() bigint 返回当前会话里最近一次nextval返回的数值。这个函数等效于currval,只是它不用序列名为参数,它抓取当前会话里面最近一次nextval使用的序列。如果当前会话还没有调用过nextval,那么调用lastval将会报错。
setval(regclass, bigint) bigint 重置序列对象的计数器数值。设置序列的last_value字段为指定数值并且将其is_called字段设置为true,表示下一次nextval将在返回数值之前递增该序列。
setval(regclass, bigint, boolean) bigint 重置序列对象的计数器数值。功能等同于上面的setval函数,只是is_called可以设置为true或false。如果将其设置为false,那么下一次nextval将返回该数值,随后的nextval才开始递增该序列。

注意序列名中有大写字母时,regclass参数值需要用双引号括和单引号一起括起来,比如:

1
select nextval('"ACT_ChecklistItem_Id_seq"');

除了setval函数,还有另一种方法也是修改sequence的start_value,也是会更新序列的当前值:

项目部署上去需要插入一些基础数据,所以新增数据的ID不是从1开始,修改sequence的start_value (下次执行nextval得到的是start_value,而不是start_value+1) 。

1
alter sequence s_seq restart with 2

相当于

1
select setval('s_seq',2,false)

从LightDB 22.2开始,lightdb完全支持oracle的seqname.nextval,seqname.currval。如下:

zjh@postgres=# select  t_id_seq.nextval;
 nextval 
---------
       1
(1 row)

zjh@postgres=# select  t_id_seq.nextval;
 nextval 
---------
       2
(1 row)

zjh@postgres=# select  t_id_seq.nextval;
 nextval 
---------
       3
(1 row)

zjh@postgres=# select  t_id_seq.nextval;
 nextval 
---------
       4
(1 row)

在lightdb内部,序列也是通过表实现的。每个序列一张表,如下:

zjh@postgres=# \ds
           List of relations
 Schema |   Name    |   Type   | Owner 
--------+-----------+----------+-------
 public | a_id_seq  | sequence | zjh
 public | t1_id_seq | sequence | zjh
 public | t_id_seq  | sequence | zjh
(3 rows)
zjh@postgres=# select * from t_id_seq;
 last_value | log_cnt | is_called 
------------+---------+-----------
          4 |      29 | t
(1 row)

 注:如果希望使用serial自动生成自增值,一定要使用bigserial,不然20亿记录的时候就溢出了。

posted @ 2022-05-14 21:20  zhjh256  阅读(65)  评论(0编辑  收藏  举报