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)
相关推荐
Karoku06626 分钟前
【企业级分布式系统】ELK优化
运维·服务器·数据库·elk·elasticsearch
小技与小术2 小时前
数据库表设计范式
数据库·mysql
安迁岚2 小时前
【SQL Server】华中农业大学空间数据库实验报告 实验三 数据操作
运维·服务器·数据库·sql·mysql
安迁岚2 小时前
【SQL Server】华中农业大学空间数据库实验报告 实验九 触发器
数据库·sql·mysql·oracle·实验报告
Loganer2 小时前
MongoDB分片集群搭建
数据库·mongodb
LKID体2 小时前
Python操作neo4j库py2neo使用之创建和查询(二)
数据库·python·neo4j
刘大浪2 小时前
后端数据增删改查基于Springboot+mybatis mysql 时间根据当时时间自动填充,数据库连接查询不一致,mysql数据库连接不好用
数据库·spring boot·mybatis
一只爱撸猫的程序猿2 小时前
简单实现一个系统升级过程中的数据平滑迁移的场景实例
数据库·spring boot·程序员
无敌岩雀2 小时前
MySQL中的索引
数据库·mysql
a_安徒生3 小时前
linux安装TDengine
linux·数据库·tdengine