ORM支持处理死锁

时间:2009-02-27 15:20:29

标签: orm deadlock

您知道任何提供死锁恢复的ORM工具吗?我知道死锁是一件坏事,但有时任何系统都会受到负载的影响。在Sql Server中,死锁消息显示“重新运行事务”,因此我怀疑重新运行死锁语句是ORM的理想功能。

5 个答案:

答案 0 :(得分:4)

我不知道有任何特殊的ORM工具支持自动重新运行因死锁而失败的事务。但是我不认为ORM使得处理锁定/死锁问题的方式大不相同。首先,您应该分析死锁的根本原因,然后以避免或至少减少死锁的方式重新设计事务和查询。有很多选项需要改进,例如为事务的(部分)选择正确的隔离级别,使用锁定提示等。这更多地取决于您的数据库系统,然后是ORM。当然,如果您的ORM允许您使用存储过程进行一些微调命令等,它会有所帮助。

如果这对完全避免死锁没有帮助,或者你现在没有时间实现和测试真正的修复,当然你可以简单地在你的save / commit / persist或者其他任何地方放置一个try / catch如果它们指示失败的事务是“死锁牺牲品”,则调用,检查捕获的异常,然后在几秒钟休眠后调用save / commit / persist。等待几秒钟是一个好主意,因为死锁通常表明存在竞争相同资源的临时交易高峰,并且一次又一次地快速重新运行相同的交易可能会使事情变得更糟。

出于同样的原因,您可能不会确保只尝试重新运行同一笔交易。

在现实世界中,我们曾经实施过这种解决方法,大约80%的“死锁受害者”在第二次成功实施。但我强烈建议深入挖掘以解决死锁的实际原因,因为这些问题通常会随着用户数量呈指数级增长。希望有所帮助。

答案 1 :(得分:1)

预计会出现死锁,而SQL Server在这方面似乎比其他数据库服务器更糟糕。首先,您应该尽量减少死锁。尝试使用SQL Server Profiler找出其发生的原因以及您可以采取的措施。接下来,如果可能,将ORM配置为在同一事务中进行更新后不读取。最后,在你完成之后,如果你碰巧一起使用Spring和Hibernate,你可以放入一个拦截器来监视这种情况。扩展MethodInterceptor并将其放在interceptorNames下的Spring bean中。运行拦截器时,使用invocation.proceed()来执行事务。捕获任何异常,并定义您想要重试的次数。

答案 2 :(得分:0)

我工作的一个系统是基于“命令”,然后当用户按下save时将其提交到数据库,它的工作原理如下:

While(true)
   start a database transaction
   Foreach command to process
      read data the command need into objects
      update the object by calling the command.run method
   EndForeach
   Save the objects to the database
   If not deadlock
     commit the database transaction
    we are done
   Else 
     abort the database transaction
    log deadlock and try again
   EndIf
EndWhile

你可以做任何与ORM相似的事情;我们使用内部数据访问系统,因为当时ORM太新了。

当用户与系统交互时,我们在事务之外运行命令。然后如上所述重新运行它们(当您使用“保存”时)以应对其他人所做的更改。由于我们已经对命令会改变的行有了很好的理想,我们甚至可以使用锁定提示或“select for update”来取出在事务开始时我们需要的所有写锁。 (我们将要更新的行集缩短以减少死锁数量)

答案 3 :(得分:0)

o / r映射器无法检测到这种情况,因为死锁始终在DBMS内部发生,这可能是由其他线程或其他应用程序设置的锁定引起的。

为确保一段代码不会造成死锁,请始终使用以下规则: - 在交易之外取货。首先获取,然后执行处理然后执行插入,删除和更新等DML语句 - 包含/使用事务的方法或一系列方法中的每个操作都必须使用与数据库相同的连接。这是必需的,因为例如通过同一连接执行的语句会忽略写锁(因为同一连接设置了锁;))。

通常会发生死锁,因为任一代码都会在事务中获取数据,从而导致打开新连接(必须等待锁定)或者对事务中的语句使用不同的连接。

答案 4 :(得分:0)

我快速看了一下(毫无疑问你也有)并且找不到任何暗示hibernate至少提供这个的东西。这可能是因为ORM认为这超出了他们试图解决的问题的范围。

如果您遇到死锁问题,请务必按照此处发布的一些建议尝试解决这些问题。之后,您只需要确保所有数据库访问代码都包含一些可以检测到死锁并重试事务的内容。