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)
相关推荐
数据库小学妹3 分钟前
企业级数据库迁移实践:从Oracle到国产数据库的兼容性与实施策略
数据库·mysql·oracle·dba
2301_779622413 分钟前
PHP处理Codex安全漏洞检测【解答】
jvm·数据库·python
一 乐4 分钟前
学院教学工作量统计|基于java+ vue学院教学工作量统计管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·学院教学工作量统计系统
六月雨滴7 分钟前
Oracle 安全架构概述
数据库·oracle·dba·安全架构
迷藏4948 分钟前
【无标题】
java·数据库·oracle
莽撞的大地瓜16 分钟前
政企舆情大数据服务平台:新浪舆情通以技术赋能全流程管理
大数据·数据库·数据分析
weixin_4597539421 分钟前
c++如何利用filesystem--relative计算两个文件之间的相对路径【详解】
jvm·数据库·python
阿福聊编程28 分钟前
Data-Analysis-Agent:用自然语言查数据库的开源 AI 数据分析工具
数据库·人工智能
行业研究员33 分钟前
2026 Agent Memory主流方案能力解析与落地选型
大数据·数据库·agent记忆
m0_5967490935 分钟前
Golang怎么实现队列数据结构_Golang如何用切片实现先进先出的队列【方法】
jvm·数据库·python