我有一个依赖于 spring-boot-starter-data-jpa
的 spring-boot 应用程序。我有一个像这样的简单存储库:
import org.springframework.data.jpa.repository.JpaRepository;
public interface FooRepository extends JpaRepository<FooEntity, Integer> {
}
我有一个像这样的简单 Controller :
@RestController
public class FooController {
private FooRepository fooRepo;
public FooController(final FooRepository fooRepo) {
this.fooRepo = fooRepo;
}
@GetMapping(value = "{id}}", produces = "application/json")
public ResponseEntity<FooEntity> getFoo(@PathVariable("id") int fooId) {
FooEntity ent = fooRepo.findOne(fooId);
return new ResponseEntity<>(ent, HttpStatus.OK);
}
}
但是我的应用程序经常遇到死锁问题。即使有 10 个用户同时尝试获取 Foo 也会导致错误:
Transaction was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
使应用程序线程中的所有数据库事务安全的最佳方法是什么?
编辑 1: 这不仅发生在获取时,也发生在保存和更新时。该问题的一种解决方案是将 Java 关键字 synchronized
添加到存储库方法中。这解决了所有死锁问题,不再担心。但这是否意味着我们必须将该关键字添加到每个 repo 方法中?是否有更可持续的解决方案?
最佳答案
正如Kayaman所说,这应该是因为写入或更新操作,但您提供的数据不能再多说了。我的猜测是一个事务在等待另一个事务结束时超时,所以它假设死锁。看看 SQL 查询日志,看看在死锁时刻正在执行什么,什么在等待,也许这可以给你一些提示。
关于java - Spring/JPA 多线程死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49305097/