JPA 锁定 PESSIMISTIC_WRITE 和 FEW 事务
Posted
技术标签:
【中文标题】JPA 锁定 PESSIMISTIC_WRITE 和 FEW 事务【英文标题】:JPA locks PESSEMISTIC_WRITE and FEW transactions 【发布时间】:2021-02-06 17:51:15 【问题描述】:我在我的存储库方法上使用 PESSEMSTIC_WRITE 锁。这就是锁定我的对象直到交易结束。但是,我遇到了一个问题,在一个端点内,控制器-> 服务-> 我开始事务然后我需要更新我的对象并将消息发送到 kafka,之后我需要在此方法中再次更新我的对象并发送到 kafka .因此,因为它是一个事务,所以更改仅在缓存中本地起作用。但是我需要保存在数据库中然后发送到 kafka,然后再次更改我的对象并保存到数据库并发送到 kafka 消息,我不能使用 REQUIRES_NEW 并以任何方式创建新事务,因为我的对象被锁定。那么我该如何处理呢? 这个锁在我的项目的许多部分中用于修复并行事务。
【问题讨论】:
我对您要解决的实际问题感到困惑。你是什么意思'我需要保存在数据库中然后发送到kafka'?当您的对象被写锁锁定时,没有其他人可以读取相应的行,此时您是否保存到数据库有什么关系?在锁被释放之前,这些更改将不可见 好吧,但是我需要这个杀手在锁定对象上保存两次,我认为业务有问题。 【参考方案1】:您应该创建将协调流程的新服务。这样你就可以在第二次操作中再次获得同样的悲观锁。
@Service
class OrchestratorService
...
void executeFlow()
someService.executeFirstOperationAndSendKafkaEvent()
someService.executeSecondOperationAndSendKafkaEvent()
@Service
class SomeService
@Transactional(REQUIRES_NEW)
void executeFirstOperationAndSendKafkaEvent()
// any lock which obtained inside this method will be released once this method finishes
...
@Transactional(REQUIRES_NEW)
void executeSecondOperationAndSendKafkaEvent()
// any lock which obtained inside this method will be released once this method finishes
...
还有一个更重要的方面值得一提——发送 kafka 事件不是事务性的。 @Transactional
只保证对数据源所做的更改将是事务性的(在本例中为数据库)。因此,以下情况是可能的:
由于这种性质,最好将流程分成几个阶段:
-
在 DB 中应用业务更改并在 DB 中存储一个应该发送 kafka 事件的标志,但尚未完成,
TX 范围外向 kafka 发送事件
在新的 TX 中更改事件已发送的标志,或在发送事件期间发生错误时安排重试。
【讨论】:
谢谢,我使用了类似的代码。我使服务 OrchestratorService 不是事务性的,然后 SomeService 使事务性,所以每次我得到一个新的事务。以上是关于JPA 锁定 PESSIMISTIC_WRITE 和 FEW 事务的主要内容,如果未能解决你的问题,请参考以下文章
Spring Data JPA / Hibernate中锁的范围是什么?
带有 PESSIMISTIC_WRITE 锁的 REPEATABLE_READ 隔离级别
Spring data Jpa,Mybatis,读写锁,@Lock 使用