【问题标题】:Read uncommited data in Spring JPA Repository在 Spring JPA 存储库中读取未提交的数据
【发布时间】:2018-02-14 12:15:30
【问题描述】:

我在 Spring Boot Application 中的服务方法被多个线程访问,一个线程正在修改 DB 中的数据。

当其他线程在第一次提交之前访问数据时,它不会获得先前线程的数据库更新。

在stackoverflow上长时间搜索后,我对相关方法使用了以下注释。

import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_UNCOMMITTED)
public void accept(Event<String> event) {}

但无法达到预期的结果。未提交的更改不会在第二个线程中检索。

请帮助我解决这个问题。

我使用了实体管理器的 flush() 方法,但没有成功。

【问题讨论】:

  • 您的数据库支持哪些隔离级别?更重要的是,为什么要另一个线程读取未提交的数据?提交它不是更好吗?
  • 如果你需要访问第一个线程修改的数据,那么你的事务是相互依赖的。 READ UNCOMMITTED 不是解决方案。您正在写入/读取哪种数据,为什么需要在提交之前访问它?
  • 实际上在第一个线程上,我锁定了数据库中的特定数据。所以当它被一个线程访问时,它不应该被其他线程访问。在我的方法中,它首先获取已解锁的数据并为它们加锁并提交给数据库。所以其他线程不应该拿起这些条目。但不幸的是,他们选择了相同的条目,因为它们还没有提交给 DB。
  • 我使用的是 PostgreSQL Db,它支持 READ_UNCOMMITTED 隔离。请帮我解决这个问题,我搞砸了。
  • 如何“锁定数据库中的特定数据”?

标签: java spring locking spring-data-jpa spring-transactions


【解决方案1】:

您混淆了隔离级别和锁。

READ_UNCOMMITTED 的隔离级别 允许 其他事务在提交之前查看您的第一个事务写入的内容。它不需要发生这种情况,也不会影响锁。但是根据您的cmets,您真正想要实现的是以某种方式正确锁定数据库行,以便其他人无法访问它们。

执行此操作的 JPA 方法是使用适当的锁定模式查询数据:

锁定模式可以通过EntityManager锁定方法、允许指定锁定模式的EntityManager、Query和TypedQuery接口的方法以及NamedQuery注解来指定。

(来自JPA Specification的3.4.4)

您可能对“悲观”变体感兴趣,这些变体阻止另一个事务在提交锁定行之前读取它们(因此锁定释放)

如果事务T1在anobject上调用lock(entity, LockModeType.PESSIMISTIC_READ)或lock(entity, LockModeType.PESSIMISTIC_WRITE),entitymanager必须保证不会出现以下两种现象:

  • P1(脏读):事务 T1 修改了一行。然后另一个事务 T2 在 T1 提交或回滚之前读取该行并获取修改后的值。
  • P2(不可重复读取):事务 T1 读取一行。在 T1 提交或回滚之前,另一个事务 T2 会修改或删除该行。

(来自JPA Specification的3.4.4.2)

您可以通过使用 @Lock 注释将这些锁定模式与 Spring Data JPA 一起使用。

【讨论】:

    猜你喜欢
    • 2020-05-01
    • 1970-01-01
    • 2015-01-27
    • 2018-05-04
    • 2017-05-26
    • 1970-01-01
    • 1970-01-01
    • 2019-12-22
    • 2011-08-29
    相关资源
    最近更新 更多