首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >并发- Spring + Hibernate + SQL Server

并发- Spring + Hibernate + SQL Server
EN

Stack Overflow用户
提问于 2021-09-01 13:33:05
回答 1查看 70关注 0票数 5

即使在spring事务中使用了可序列化的隔离级别,我也遇到了并发问题。我的用例是,用户将以以下格式提供要在数据库中更新的配置。

代码语言:javascript
复制
{A1: [B1, B2, B3]}

我必须将它保存在下面的实体中。

代码语言:javascript
复制
A {
    @OneToMany
    List<B> bList;
}

B {
    @ManyToOne
    A a;
    
    Boolean isDeleted;
}

当存在保存配置的并发请求时,会插入比预期更多的B。请参考下面的场景。

代码语言:javascript
复制
Initial enitites in database: A1 -> []

Transaction 1 - given config {A1: [B2]}

Reads A1 -> []
Insert B2

Transaction 2 - given config {A1: [B3]}

Reads A1 -> []
Insert B3

Final in database: A1 -> [B2, B3] when expected is either A1 -> [B2, B3-deleted] or A1 -> [B2-deleted, B3].

即使经过大量的研究,我也找不到解决这个问题的适当方法。根据本文(https://sqlperformance.com/2014/04/t-sql-queries/the-serializable-isolation-level),当使用SQL Server作为操作顺序是有效的序列化之一时,这种情况总是可能发生的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-13 07:33:19

这最好通过引入乐观锁定的版本列来处理。不需要使用SERIALIZABLE隔离级别。只需使用

代码语言:javascript
复制
A {
    @Version
    long version;
    @OneToMany
    List<B> bList;
}

并确保在加载A时使用LockModeType.OPTIMISTIC_FORCE_INCREMENT。这样,“序列化”将基于所谓的“聚合根”的锁,即A

通过这样做,一个事务将成功,另一个事务将失败,因为在每个事务结束时,只有在其间值不变的情况下,version列才会递增。如果在此期间发生更改,它将回滚两个事务中的一个,您将看到一个OptimisticLockException。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69014760

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档