【发布时间】:2020-10-07 15:40:18
【问题描述】:
我继承了一个使用 Spring MVC 和 Hibernate 存储到 DB2 数据库中的系统。最近它开始出现看起来像 DB2 报告的死锁问题,所以我一直在调试它。我不是 Spring 或 Hibernate 专家,但我两者都知道。
代码结构如下:
controller -> service -> one or more DAO classes that performs the updates
在出现问题的情况下,控制器调用一个带有@Transactional 和@Override 注释的服务方法。该服务转到使用@Repository 注释的DAO 类,并调用使用@Transactional 和@Override 注释的多个方法。这就是代码的结构。
一个控制器调用一个服务方法。服务方法调用多个 DAO 方法。大多数 DAO 方法都标记为@Transactional 和@Override。一些在@Transactional 中有 REQUIRES_NEW。同样在每个 DAO 方法中,Session 由 SessionFactory.getCurrentSession() 获取。
第一个问题:使用这种方法,事务从哪里开始,最终提交在哪里?和回滚?这些都没有明确编码。
当其中一个方法更新记录,然后后续方法删除同一记录时,就会出现死锁。如果您想知道为什么有人想要这样做,更新会添加想要删除记录中信息的人的用户 ID,以便可以通过存储过程将其保存到另一个表中。然后第二个方法调用删除记录。
最初的编码员尝试将 REQUIRES_NEW 添加到 @Transactional,认为新事务将确保更新发生。但死锁仍然不定期发生。
我尝试将更新更改为原生 SQL 调用,但 Hibernate 不允许我启动另一个事务,因为一个事务已经打开。
这里有人有什么指导吗?
【问题讨论】:
-
编辑了我原来的帖子来回答你的问题。
-
是的,我确实发现 Hibernate 会忽略我假设的更新,因为它看到记录将被删除,但我不希望这样,因为在更新记录后类似于存储过程(在本例中是 DB2 的时态表系统)将记录复制到历史表中。最终发生的是 Hibernate 尝试首先更新一条记录(这导致 DB2 将该记录复制到另一个表),然后删除该记录。因此,正在对同一记录尝试三个数据库操作,我敢打赌这会导致死锁。
-
死锁是两个事务互相等待放弃锁。
标签: java spring hibernate db2 database-deadlocks