18

我需要一个特定的业务场景来在一个实体(不是 PK)上设置一个来自序列的数字(序列必须是 min 和 max 之间的数字)

我定义了这样的序列:

CREATE SEQUENCE MySequence
  MINVALUE 65536 
  MAXVALUE 4294967296 
  START WITH 65536
  INCREMENT BY 1
  CYCLE
  NOCACHE
  ORDER;

在 Java 代码中,我从这样的序列中检索数字:

select mySequence.nextval from dual

我的问题是:

如果我select mySequence.nextval from dual在一个事务中调用这个“”并且在另一个事务中同时调用相同的方法(并行请求),那么确定序列返回的值是不同的吗?

不可能像从第一笔交易中读取未提交的值吗?

因为假设我不会使用序列和一个普通表,我会在其中增加自己的序列,那么如果 trasactinalitY 是默认的“READ COMMITTED”,那么事务 2 将能够读取相同的值。

4

4 回答 4

40

答案是不。

Oracle 保证序列生成的数字是不同的。即使发出并行请求,RAC 环境或回滚和提交也是混合的。

序列与事务无关。

请参阅此处的文档

使用 CREATE SEQUENCE 语句创建一个序列,这是一个数据库对象,多个用户可以从中生成唯一 整数。您可以使用序列自动生成主键值。

生成序列号时,序列会递增, 与事务提交或回滚无关。如果两个用户同时递增同一个序列,那么每个用户获取的序列号可能会有间隙,因为序列号是由另一个用户生成的。一个用户永远无法获得另一个用户生成的序列号。在一个用户生成序列值后,该用户可以继续访问该值,而不管该序列是否由另一个用户递增。

序列号是独立于表生成的,因此可以为一个或多个表使用相同的序列。个别序列号可能会被跳过,因为它们是在最终回滚的事务中生成和使用的。此外,单个用户可能没有意识到其他用户正在从同一序列中绘图。

于 2012-08-24T07:03:56.677 回答
7

Oracle 保证序列号会有所不同。即使您的事务被回滚,该序列也被“使用”并且不会重新发布给另一个查询。

编辑:在 Cris 的评论中说明围绕“无间隙”的要求后添加附加信息

如果您的要求是一个没有间隙的数字序列,那么 oracle 序列可能不是一个合适的解决方案,因为在事务回滚时,或者当数据库重新启动或任何其他数量的场景时会出现间隙。

序列的主要目的是作为唯一数字(例如主键)的高性能生成工具,而不考虑间隙和事务上下文约束。

如果您的设计/业务/审计要求需要考虑每个数字,那么您需要设计一个在事务上下文中使用预定数字的解决方案。在多线程环境中,这可能很棘手并且容易出现性能/锁定问题。最好尝试重新定义您的要求,这样差距就无关紧要了。

于 2012-08-24T06:57:14.497 回答
4

sequence.nextval永远不会为并发请求返回相同的值(循环之前)。也许您应该检查以下 URL:

http://docs.oracle.com/cd/B19306_01/server.102/b14220/schema.htm#sthref883

于 2012-08-24T06:56:53.767 回答
1

不幸的是,你必须实现你自己的轮子——事务序列。这相当简单 - 只需创建像 sequence_name varchar2、value、min_value number、max_value number、need_cycle char 这样的表,然后搞乱“从序列表中选择值到变量中以进行更新等待(或 nowait - 这取决于您的场景)”。在它发出 update set value = variable from previous step + 1 其中 sequence_name = 您的序列的名称并从客户端发出提交语句之后。就是这样。

于 2012-08-24T07:08:35.070 回答