【问题标题】:Oracle Sequence TransactionalityOracle 序列事务性
【发布时间】:2012-08-19 17:21:24
【问题描述】:

我需要针对特定​​的业务场景在实体(不是 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 将能够读取相同的值。

【问题讨论】:

  • 为什么没有缓存和订单?这对性能没有好处。
  • 由于业务限制,导致需要使用序列中的每个数字。如果使用缓存并且数据库服务器停止运行,甚至 1 分钟都停止了,我知道缓存的序列号会丢失。
  • 即使没有缓存,你也会丢失数字。考虑获取序列和回滚。在这种情况下,你确实有差距。
  • 嗯,有这种情况,用于恢复丢失的号码,并且会有一些,因为回滚不是很频繁。使用缓存可能会使差距更大。这是一个问题,如果? ...如果我们使用缓存,性能会提高...

标签: java sql oracle hibernate sequence-sql


【解决方案1】:

答案是否定的。

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

序列与事务无关。

here the docs:

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

当一个序列号产生时,序列递增, 独立于事务提交或回滚。如果两个 用户同时增加相同的序列,然后序列 每个用户获取的数字可能有间隙,因为序列号是 由其他用户生成。一个用户永远无法获得 另一个用户生成的序列号。在一个序列值之后 由一个用户生成,该用户可以继续访问该值 不管序列是否被其他用户递增。

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

【讨论】:

  • 这实际上意味着:Oracle 的序列可以生成唯一值,但不是 DBMS 的 ACID 兼容事务模型的一部分,而是与其一起使用的免费设施/工具。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

    编辑:在 Cris 在 cmets 中说明“无间隙”的要求后添加额外信息

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

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

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 对于将答案标记为否定的人:您建议采用哪种方式来创建交易序列? my one 是唯一一种可能,而且由我实现并在我的各种项目中使用。
      • 我不知道谁投了反对票,但是我不想要一个事务序列,我询问了一个事实,如果一个 oracle 序列受事务影响。我现在投了赞成票,感谢您的回复.干杯
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-25
      • 1970-01-01
      • 1970-01-01
      • 2013-01-02
      • 2019-12-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多