gpt4 book ai didi

mysql - Spring @Transactional 死锁

转载 作者:可可西里 更新时间:2023-11-01 08:54:25 26 4
gpt4 key购买 nike

我有以下设置。

  • Spring 3.0.5
  • 休眠 3.5.6
  • MySql 5.1

要通过 Hibernate 在数据库中保存记录,我有以下工作流程

  1. 将 JSON {id:1,name:"test",children:[...]} 发送到 Spring MVC App 并使用 Jackson 将其转换为对象图(如果它是一个现有实例 JSON 具有数据库集中记录的正确 ID

  2. 通过服务层调用将对象保存在数据库中(详情如下)

    • 服务层接口(interface)SomeObjectService的保存函数有@Transactional注解,readOnly=false和Propagation REQUIRED

    • 这个服务层SomeObjectServieImpl的实现调用DAO保存方法

    • DAO 通过调用 hibernate 的合并来保存新数据,例如hibernateTempate().merge(someObj)

    • hibernate merge 首先通过 SELECT

      从 DB 加载对象
    • 我有一个连接到 spring 的 EntityListener(我使用了这种技术 Spring + EntityManagerFactory +Hibernate Listeners + Injection )并监听 @PostLoad

    • 监听器使用 LockingServie 更新 someObject 的一个字段以将其设置为锁定(这实际上应该只发生在 someObject 通过 Hibernate HQL、SQL 或 Criteria 调用加载,但也会在合并时调用)

    • LockingServie 有一个函数 lock(someObj,userId) 也用 @Transactional 和 readOnly=false 注释并且必需

    • 通过调用 Query query = sess.createQuery("update someObj set lockedBy=:userId"); 进行更新,然后query.executeUpdate();

    • 合并加载数据后,它开始更新 someObject 并插入相关子对象(<= exacely 这里是死锁发生的地方)

  3. 将 JSON 结果(这也包括新创建的对象 ID)返回给客户端。

问题首先出现在我身上

  1. 记录在事务中加载
  2. 然后在另一个(内部)事务中进行更改
  3. 然后应该使用外部事务的数据再次更新,但因为它被锁定而无法更新。

我可以通过MySQL看到

SHOW OPEN TABLES 

子表(对象图的一部分)被锁定。

有趣的是,死锁不是发生在 someObj 表上,而是发生在代表 child 的表上。

我有点迷路了。我们非常欢迎任何帮助。

顺便说一句,也许可以 isolation水平让我摆脱这个问题吗?

最佳答案

我最终使用了@Bozho 的 HibernateExtendedJpaDialect

这里有解释>> Hibernate, spring, JPS & isolation - custom isolation not supported

将隔离设置为READ_UNCOMMITED

@Transactional(readOnly = false, propagation = Propagation.REQUIRED, isolation=Isolation.READ_UNCOMMITTED)
public Seizure merge(Seizure seizureObj);

我知道这不是一个很好的解决方案,但至少这解决了我的问题。

如果有人想要详细的描述,请询问...

关于mysql - Spring @Transactional 死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7947582/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com