IvorySQL 3.4:如何实现兼容Oracle风格的序列功能?

1

什么是序列?

一个序列是一个数据库对象,与表和视图类似,它表示可以由全局数据库命名空间中的任何表和视图使用的整数序列。可以使用NEXTVAL和CURRVAL访问序列值。序列可以是升序或降序。

2

Oracle的序列相比PG多了什么?

  • 支持CACHE/NOCACHE、SCALE、SESSION、GLOBAL特性;

  • 支持NEXTVAL和CURRVAL伪列实现;

  • 支持三个序列视图,ALL_SEQUENCES、DBA_SEQUENCES、USER_SEQUENCES;

3

3.4 的设计概述

为了兼容oracle中sequence的特性与功能,我们主要处理工作有以下几个方面:

  • 语法修改,兼容oracle序列的部分语法。

  • 功能实现,实现兼容oracle的部分序列功能。

  • 序列调用的兼容,支持NEXTVAL和CURRVAL伪列使用序列值。

  • 序列相关视图的创建以及序列的备份相关内容。

4

3.4 具体特性

4.1 CACHE/NOCACHE兼容
  • Oracle中CAHCHE只能指定为大于1的值,而PG中可以指定大于0的值。IvorySQL采用了与Oracle相同的做法;

  • 新增关键字NOCACHE,指定NOCACHE时cache值为1,不指定时cache值默认为20;

>>>指定nocache的情况下,cache_size的值为1。
复制代码
create sequence seq_cache nocache;select cache_size from all_sequences where sequence_name='seq_cache'; cache_size ------------          1(1 row)
>> > ********不指定nocache的情况下,cache_size的默认值为20。********​​​​​​​
复制代码
create sequence seq_cache;select cache_size from all_sequences where sequence_name='seq_cache'; cache_size ------------         20(1 row)
  • PG中指定cache大于1时,多个会话之间的序列值会出现间隙,间隙值为cache值,即每个会话缓存了对应序列值,后续会话会从上一个会话缓存后的序列开始计算。而oracle中不同会话中共享一个缓冲序列。IvorySQL沿用了PG的规则;
4.2 SESSION/GLOBAL实现
  • **GLOBAL:**全局序列,会话之间共用一个序列,该选项为默认选项。

  • **SESSION:**每个会话重新登录都会拥有一个起始的序列值,会话之间序列相互不影响。

4.3 RESTART语法功能支持

指定RESTART时,序列值从初始值开始计算,在ALTER中要修改序列的起始值需要和START WITH一起使用以修改序列的起始值。

>> > ********示例:********​​​​​​​
复制代码
CREATE SEQUENCE seq_restart INCREMENT BY 1 START WITH 32 MINVALUE 10 MAXVALUE 50;select seq_restart.nextval from dual; nextval ---------      32(1 row)
alter sequence seq_restart restart;
Restart后序列值从初始值开始计算。select seq_restart.nextval from dual; nextval ---------      10(1 row)
4.4 SCALE序列范围伸缩

SCALE强制将额外的6位数字添加在序列值的前面,组成一个新的序列值,即新的序列值= 6个数字 || 普通序列值。

额外6位数= [system_identifier%100+100] || [session_id%1000]。

这额外的6位数不存储于表中,且默认最大值的情况下加上这6位数值已经超过了bigint的最大值,所以如果指定的最大序列值数大于13位,则报超过序列最大值的错误。

EXTEND和NOEXTEND的区别在于EXTEND会比最大值多6位,而NOEXTEND会跟最大值保持位数相同,设计时需要注意如果maxvalue的最大值位数小于6位时,调用nextval将会报错,或者当nextval获取的NOEXTEND值大于maxvalue时也会报错。

>> > ********示例:********​​​​​​​
复制代码
指定extend 的情况下,额外的6位数字添加在序列值的前面。ivorysql=# CREATE SEQUENCE seq scale extend maxvalue 99999999;CREATE SEQUENCEivorysql=# select seq.nextval from dual;    nextval     ---------------- 17400100000001(1 row)
ivorysql=# DROP SEQUENCE seq;DROP SEQUENCE
指定noextend 的情况下,额外的6位数字嵌在序列值的前部。ivorysql=# CREATE SEQUENCE seq scale noextend maxvalue 99999999;CREATE SEQUENCEivorysql=# select seq.nextval from dual; nextval  ---------- 17400101(1 row)
4.5 NEXTVAL和CURRVAL伪列实现

序列值的引用Oracle使用了NEXTVAL和CURRVAL两个伪列来实现,PG中则使用了NEXTVAL()和CURRVAL()函数来实现,所以在语法分析层当识别到使用了NEXTVAL和CURRVAL伪列引用序列时,将其转换成NEXTVAL()或CURRVAL()函数的调用,以达到实现伪列引用的目的。

4.6 序列相关视图实现

实现ALL_SEQUENCES、DBA_SEQUENCES、USER_SEQUENCES三个视图。

序列的视图实现主要依赖于系统表pg_sequence。序列视图中SHARDED_FLAG和KEEP_VALUE列由于只实现了语法功能,所以这两列的内容为空。

>> > ********示例:********​​​​​​​
复制代码
使用USER_SEQUENCES视图ivorysql=# select min_value, max_value from user_sequences where sequence_name = 'seq'; min_value | max_value -----------+-----------         1 |  99999999(1 row)
使用ALL_SEQUENCES视图ivorysql=# select cache_size from all_sequences where sequence_name='seq'; cache_size ------------         20(1 row)
相关推荐
豆芽脚脚2 小时前
合并相同 patient_id 的 JSON 数据为数组
postgresql·json
·薯条大王4 小时前
MySQL联合查询
数据库·mysql
yuzhangfeng4 小时前
【云计算物理网络】从传统网络到SDN:云计算的网络演进之路
网络·云计算
morris1316 小时前
【redis】redis实现分布式锁
数据库·redis·缓存·分布式锁
hycccccch6 小时前
Canal+RabbitMQ实现MySQL数据增量同步
java·数据库·后端·rabbitmq
这个懒人7 小时前
深入解析Translog机制:Elasticsearch的数据守护者
数据库·elasticsearch·nosql·translog
Yan-英杰7 小时前
【百日精通JAVA | SQL篇 | 第二篇】数据库操作
服务器·数据库·sql
ZStack开发者社区7 小时前
全球化2.0 | ZStack举办香港Partner Day,推动AIOS智塔+DeepSeek海外实践
人工智能·云计算
NineData7 小时前
NineData云原生智能数据管理平台新功能发布|2025年3月版
数据库
百代繁华一朝都-绮罗生9 小时前
检查是否存在占用内存过大的SQL
数据库·sql