我们在数据库事务中看到了奇怪的行为 - 它们的行为不是原子的。我们使用 MySQL 5.6.25 Innodb、Eclipselink 2.5.2 作为 JPA 提供程序,使用 HikariCP 2.6.2 作为连接池。
当 Eclipselink 在entityManager.flush 调用期间无法从池中获取连接时,就会出现此问题。有一段时间,我们接受了这个异常,因为对特定表的条目是在尽力而为的基础上进行的——可以说是一种审计模式。然而,这导致只提交了事务的一部分 - 在 5 个事务中,只有 1,2 或 3 个条目被持久化。
当然,这是事件的流程
tx.begin();
em.persist(entity1);
try{
em.persist(entity2);
em.flush(); ---> this is where connection acquisition fails.
} catch(Throwable tx){
//do nothing, except log.
}
em.persist(entity3);
em.flush();
em.persist(entity4);
em.flush();
em.persist(entity5);
em.flush();
em.persist(entity6);
tx.commit();
我们看到事务已提交到实体3、实体4、实体5,此时连接获取在稍后刷新的某个时刻再次失败。
谁能指出这是如何发生的?
最佳答案
您面临的主要问题是连接不可用。此类异常必须导致事务回滚。
捕获那些未处理的事务将改变事务的行为。第一个 em.flush()
期间的异常也会消除您不想丢失的第一个 em.persist(entity1)
。
因此,解决方案是在 try
之前添加 em.flush()
,以确保实体 1 的持久性得到保证,否则会导致异常导致整个事务回滚。
不过我不会推荐这种解决方案。
如果持久化 entity2
是可选的,那么通常您可以在额外的事务中执行此操作,这意味着系统将需要(在短时间内)为此提供额外的数据库连接。
如何创建额外交易?在 Ejb 中,您使用 REQUIRES_NEW 带注释的方法。我不确定您在这里使用的是哪种 TransactionManagement,但我非常确定应该有可能创建一种单独的事务(不要与嵌套事务混淆!!)。
关于mysql - 非原子行为 Eclipselink-半提交的数据库事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46504528/