gpt4 book ai didi

java - JPA 嵌套事务和锁定

转载 作者:IT老高 更新时间:2023-10-28 20:59:58 29 4
gpt4 key购买 nike

考虑两种方法存在于不同无状态bean中的场景

public class Bean_A {
Bean_B beanB; // Injected or whatever
public void methodA() {
Entity e1 = // get from db
e1.setName("Blah");
entityManager.persist(e1);
int age = beanB.methodB();

}
}
public class Bean_B {
//Note transaction
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void methodB() {

// complex calc to calculate age
}

}

由 BeanA.methodA 启动的事务将被暂停,新事务将在 BeanB.methodB 中启动。如果 methodB 需要访问由 methodA 修改的同一实体怎么办。这会导致死锁。是否可以在不依赖隔离级别的情况下防止死锁?

最佳答案

嗯,让我们列出所有情况。

REQUIRES_NEW 并不真正嵌套事务,但正如您提到的那样暂停当前事务。然后只有两个事务访问相同的信息。 (这类似于两个常规并发事务,只是它们不是并发的,而是在同一个执行线程中)。

T1 T2          T1 T2
― ―
| |
|
― | ―
| | |
| = | |
― | ―
|
| |
― ―

那么我们需要考虑乐观悲观锁定。

此外,我们需要考虑由 ORM 操作的 flushes。使用 ORM,我们在写入发生时没有明确的控制,因为 flush 是由框架控制的。通常,在提交之前会发生一次隐式刷新,但如果修改了许多条目,框架也可以进行中间刷新。

1) 让我们考虑乐观锁定,其中读取不获取锁,但写入获取排他锁。

T1 的读取没有获取锁。

1a) 如果 T1 确实提前刷新了更改,但它获得了排他锁。当 T2 提交时,它会尝试获取锁但不能。 系统被阻塞。这可能是一种特殊的死锁。完成取决于事务或锁定如何超时。

1b) 如果 T1 没有提前刷新更改,则没有获得锁。当 T2 提交时,它会获取并释放它并成功。当 T1 尝试提交时,它会注意到冲突并失败。

2) 让我们考虑悲观锁,其中读取获取共享锁并写入排他锁。

T1 读取获取共享锁。

2a) 如果 T1 过早刷新,它会将锁变成排他锁。情况类似于 1a)

2b) 如果 T1 没有提前刷新,则 T1 持有共享锁。当 T2 提交时,它会尝试获取排他锁并阻塞。 系统再次被封锁

结论:如果没有发生过早刷新,乐观锁定就可以了,这是您无法严格控制的。

关于java - JPA 嵌套事务和锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10736862/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com