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)
相关推荐
程序猿进阶25 分钟前
系统上云-流量分析和链路分析
java·后端·阿里云·面试·性能优化·系统架构·云计算
爱吃烤鸡翅的酸菜鱼1 小时前
MySQL初学之旅(1)配置与基础操作
java·数据库·mysql·database
三日看尽长安花3 小时前
【分布式数据库】
数据库·分布式
hummhumm4 小时前
Oracle 第22章:数据仓库与OLAP
java·javascript·后端·python·sql·mysql·database
一 乐7 小时前
家常菜点餐|基于java和小程序的家庭大厨家常菜点餐系统设计与实现(源码+数据库+文档)
java·数据库·小程序·家庭点餐小程序·家庭家常菜点餐
小小不董7 小时前
Oracle OCP认证考试考点详解082系列08
linux·运维·服务器·数据库·oracle·dba
lu9up8 小时前
Oracle 11g DataGuard GAP处理
oracle·dataguard·gap
王哲晓8 小时前
第一章 微服务入门
java·数据库·微服务
DarkAthena8 小时前
【MogDB】MogDB5.2.0重磅发布第五篇-支持部分ORACLE的HINT
数据库·oracle·opengauss
PythonFun8 小时前
Python常用脚本集锦
java·数据库·python