【问题标题】:EclipseLink generates duplicate primary keys on an Oracle DBEclipseLink 在 Oracle DB 上生成重复的主键
【发布时间】:2014-12-17 16:15:06
【问题描述】:

我正在使用 EclipseLink 2.4.2(与 Spring 结合使用,但我认为这与我们这里的问题无关)并且我们有几次出现以下异常:

org.springframework.transaction.TransactionSystemException:无法提交 JPA 事务;嵌套异常是 javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.2.v20130514-5956486): org.eclipse.persistence.exceptions.DatabaseException

内部异常:java.sql.SQLIntegrityConstraintViolationException:ORA-00001:违反了唯一约束 (****.PK_*****)

我们的主键是由 EclipseLink 生成的,它使用 Oracle 序列来分配它们。我仔细检查了,allocationSize 与序列中定义的increment by 完全匹配。

下面是如何在我们的 Java 类中定义此序列的示例:

@Id
@SequenceGenerator(name = "SOME_GENERATOR", sequenceName = "SOME_SEQ", allocationSize = 10000, initialValue = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SOME_GENERATOR")
@Column(name = "ID")
private Long id;

这里是创建序列的 SQL 语句:

CREATE SEQUENCE SOME_SEQ INCREMENT BY 10000 START WITH 10000;

当然,这个问题很难重现,只是随机发生。当服务器负载过重时,这种情况似乎更频繁地发生。

我不知道这是否相关,但这里有一些额外的信息:

  • 我们有两台服务器访问同一个数据库
  • 主键定义被许多类继承

我的第一个想法是这与并发有关,但对于这样一个成熟的框架来说,这似乎是一个相当严重的问题。还有什么我应该验证或我可能忽略的事情吗?

我看过相关的帖子,比如这些帖子:

但它们似乎对我没有帮助。

【问题讨论】:

  • 你能确定用于失败语句的值,以及数据库中序列的值吗?
  • @Chris 不幸的是没有。这些错误仅在我们运行并行运行的自动化测试时发生。 SQL 参数记录被禁用。我不确定获得这些值是否会帮助我找到问题。但是,如果您对我如何从这些值中追溯错误(在我的代码或 EL 中)有指导意见,我会非常感兴趣。
  • 没有什么特别的,只是寻求任何可以帮助找出使用相同编号的两个进程的特殊之处以及它们是如何获得的信息
  • @Chris 我们实际上设法发现了错误是如何发生的。问题来自“Reset of DB”和 EclipseLink 预分配 id 的错误组合。

标签: java oracle jpa eclipselink


【解决方案1】:

我们最终找到了对此问题的解释。

实际问题来自于数据库已重置(因此删除表和序列,然后重新初始化所有内容),但应用程序服务器没有。

  • 所以一开始,EclipseLink 仍然从之前的预分配队列中分配 id(例如,[100016,100017,100018,100019,100020]]。
  • 然后当它到达末尾时,它从初始值([1,2,3,4,5,...])重新开始。
  • 过了一会儿,EclipseLink 到达了已经分配的 ID,因此我们遇到了这个主键约束违规。

由于 id 被多个实体使用,因此行为相当随机,实际上不太可能发生冲突。

开发人员和测试人员现在将始终在重置 DB 后重新启动应用程序服务器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-19
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 2012-12-11
    相关资源
    最近更新 更多