因此,这似乎是一个非常菜鸟的问题,但经过一番谷歌搜索后,我找不到最佳方法。
问题:具有一个Spring-Boot应用程序,可与数据库(MySQL)交互。 考虑一个表T1,我不想为每个用户只有一个有效条目。 因此,如果出现下一个条目,它将软删除(通过设置Deleted-at列)该用户的现有行并创建一个新条目。 现在问题来了,几乎同时存在多个请求。
我的交易区块,看起来像这样:
@Transactional
someMethod() {
CheckIfAnyValidEntryForUser(U1);
SoftDeleteExistingEntries(U1);
DoComputation(); // Takes around a second.
InsertNewRow();
}
现在,如果短时间内有多个请求,那么我的代码最终将为单个用户插入多个有效条目。
由于我要编辑的行可能以前不存在,因此无法按版本号进行乐观锁定。
本来想在此someMethod上获取Global-Lock,但这会使我的等待时间增加太多。
另一种方法可能是在数据库中为列(包括Deleted-at列)使用复合唯一键。然后处理代码中的提交失败。
这似乎是一个非常普遍的问题,那么通常如何处理? 最好的方法是什么?
答案 0 :(得分:2)
您可以使用isolation
批注的@Transactional
属性,并将此属性设置为Isolation.SERIALIZABLE
:
@Transactional(isolation= Isolation.SERIALIZABLE)
请注意:
默认情况下,Spring使用 DEFAULT 隔离策略,该策略使用基础数据存储区的默认隔离级别。使用 SERIALIZABLE 隔离使您的事务在读取,写入和范围锁定时执行;所以它们看起来好像被执行了一样 以序列化的方式,防止脏读,不可重复读和 幻像读取。
也
专门设计用于Propagation.REQUIRED或Propagation.REQUIRES_NEW,因为它仅适用于新启动的交易。如果希望在参与具有不同隔离级别的现有事务时拒绝隔离级别声明,请考虑在事务管理器上将“ validateExistingTransactions”标志切换为“ true”。