7

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

4

5 回答 5

4

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

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

出于同样的原因,您可能不会确保只尝试一次以重新运行相同的事务。

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

于 2009-03-01T19:01:21.970 回答
1

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

于 2009-03-01T19:05:12.960 回答
0

我工作的一个系统是基于“命令”,然后当用户按下保存时,这些“命令”被提交到数据库,它的工作原理是这样的:

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 太新了。

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

于 2009-03-03T15:38:54.390 回答
0

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

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

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

于 2009-03-04T11:59:41.990 回答
0

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

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

于 2009-03-07T10:01:39.923 回答