我有一个api更新数据库中的某些记录。我可能有多台计算机运行相同的应用程序,所以我不能用程序而是用数据库锁定它。我想在读取记录时“锁定”记录,并在将值更新到数据库后释放记录。如果两个请求一起(或在很短的时间内)到达服务器,我希望一个计算可以等待另一个请求的交易结束,并基于另一个请求的值。
例如,
| <-- database has a record whose value is 1 | | <-- request 1 arrives and get the record with value 1 and lock the record | <-- request 2 arrives and find the record is locked therefore wait until it is ready | | <-- request 1 calculate value += 1 | | <-- request 1 update the record and unlock the record | | <-- record has value of 2 now | | <-- request 2 can get the record now, whose value is 2 and lock the record | | <-- request 2 calculate value += 1 | | <-- request 2 update the record and unlock the record | | <-- record has value of 3 now | v
我使用的数据库是Oracle。我正在使用Spring Data JPA运行查询。我尝试过的是:
控制器:
@GetMapping("/lock")
public @ResponseBody
String pessimisticLock() throws InterruptedException {
testService.readAddOneThenSave();
return "Hello World";
}
服务:
@Transactional // to release lock after the method ends
public void readAddOneThenSave() throws InterruptedException {
// get the record and lock it with PESSIMISTIC_WRITE
TestLock testLock = testLockRepository.findById(1L);
// but both machine show the original value :(
logger.info("testLock: {}", testLock);
// to simulate two requests arrive same time
Thread.sleep(5000);
Long value = testLock.getValue();
logger.info("value: {}", value);
testLock.setValue(value + 1);
testLockRepository.save(testLock);
}
存储库:
// lock when called and release until end of transaction
@Lock(LockModeType.PESSIMISTIC_WRITE)
TestLock findById(Long id);
我尝试在两台计算机上运行该应用程序,并在“相同”时间提出请求。在第一个请求结束后,第二个请求开始查找记录,但是即使在后一个请求的计算机上,我仍然从两台计算机上获得了相同的记录(值= 1)。然后,我将从上面的示例中得到值2的结果,这不是我想要的。
我对PESSIMISTIC_WRITE的理解正确吗?
感谢您的帮助。谢谢!