Hibernate 理解循环内事务中的grails死锁

Hibernate 理解循环内事务中的grails死锁,hibernate,grails,deadlock,database-deadlocks,Hibernate,Grails,Deadlock,Database Deadlocks,当前在循环内的事务上存在事务死锁: def method() { attemptIds.each { attemptId -> Attempt.withTransaction { def attempt = Attempt.findById(attemptId, [lock:true]) attempt.refresh() //modify attempt and save }

当前在循环内的事务上存在事务死锁:

def method() {
    attemptIds.each { attemptId ->
        Attempt.withTransaction {
            def attempt = Attempt.findById(attemptId, [lock:true])
            attempt.refresh()
            //modify attempt and save
        }
    }
}
此方法位于非事务性服务中。并且正在同时调用该方法。列表上的AttempId在AttempId中可能重复/不唯一

因此,对尝试的处理应该是对正在处理相同尝试的其他线程的阻塞

我们将事务包含在循环中,认为它将立即提交事务,让其他线程更新先前锁定的尝试

日志表明,findBy查询正被另一个查询阻止,反之亦然,我不确定这是怎么可能的


您认为死锁发生的原因是什么?

为什么在执行查找后要刷新?这很可能与
数据源.groovy中数据库的隔离级别有关。您使用的是什么数据库引擎/服务器,默认的数据库隔离级别是什么,以及您在
数据源.groovy
?@Deigote中定义了什么(即使您没有定义),因为尝试是同时修改的,我们只需要确保当前事务的副本不过时。事务的目的是在执行期间隔离“数据库状态”。它们的目的是使许多并发事务的结果看起来像是顺序执行的(以任何可能的顺序)。如果你想要完全相反的结果,那么使用它们有什么意义呢?@Deigote没有试图做相反的事情。我刚刚在事务上方编写了其他代码,它也执行查询尝试。由于hibernate缓存了这些数据,在find and lock语句之后,它可能不会再被更新。为什么在执行find之后要刷新?这很可能与
数据源.groovy中数据库的隔离级别有关。您使用的是什么数据库引擎/服务器,默认的数据库隔离级别是什么,以及您在
数据源.groovy
?@Deigote中定义了什么(即使您没有定义),因为尝试是同时修改的,我们只需要确保当前事务的副本不过时。事务的目的是在执行期间隔离“数据库状态”。它们的目的是使许多并发事务的结果看起来像是顺序执行的(以任何可能的顺序)。如果你想要完全相反的结果,那么使用它们有什么意义呢?@Deigote没有试图做相反的事情。我刚刚在事务上方编写了其他代码,它也执行查询尝试。由于hibernate缓存了它,所以在find and lock语句之后,它可能不再被更新。