mysql - 非原子行为 Eclipselink-半提交的数据库事务

标签 mysql jpa transactions eclipselink hikaricp

我们在数据库事务中看到了奇怪的行为 - 它们的行为不是原子的。我们使用 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/

相关文章:

mysql - 日期格式和 SQL 查询说明

php - MySql - 如何按设定的时间间隔选择一系列 id

java - Vaadin 和 JPA 容器,是否存储 beans

session 关闭时的 NHibernate 事务管理

spring - XA 事务和消息总线

php - 从表中提取上周的数据

mysql - Mysql group_concat 对连接列进行排序正确,但对其余列排序不正确?

java - 为什么 JPA 实体选择结果在每个偶数查询上都会发生变化?

Java JPA 类转换器

c# - 在 Windows Workflow Foundation 的 TransactionScope 中跨多个事件使用相同的数据库连接?