Hibernate是否会在死锁后自动重启事务?

关于这个话题已经有很多文章了:

  • 死锁后重新启动MySQL中的事务
  • 尝试锁定时发现死锁; 尝试重新启动事务:@RetryTransaction
  • MySQL JDBC:在InnoDB死锁之后是否有自动重试的选项?
  • 解决MySQL错误“试图锁定时发现死锁;尝试重新启动事务”
  • ... 还有很多
  • 我发现最后接受的答案特别有趣:

    如果您正在使用InnoDB或任何行级事务性RDBMS,则任何写入事务都可能导致死锁,即使在完全正常的情况下也是如此。 较大的表,较大的写入和较长的事务块通常会增加发生死锁的可能性。 在你的情况下,这可能是这些的组合。

    这意味着我们永远无法阻止他们,但只能对付他们。 真的吗? 我想知道是否可以防止网上有1000人在线调用写入数据库操作的死锁。

    在该主题上使用Google搜索没有得到任何有趣的结果。 我发现只有一个是(http://www.coderanch.com/t/415119/ORM/databases/Deadlock-problems-Hibernate-Spring-MS):

    public class RestartTransactionAdviser implements MethodInterceptor {
        private static Logger log = Logger.getLogger(RestartTransactionAdviser.class);
    
        public Object invoke(MethodInvocation invocation) throws Throwable {
            return restart(invocation, 1);
        }
    
        private Object restart(MethodInvocation invocation, int attempt) throws Throwable {
            Object rval = null;
            try {
                rval = invocation.proceed();
            } catch (Exception e) {
                Throwable thr = ExceptionUtils.getRootCause(e);
                if (thr == null) {
                    throw e;
                }
    
                if (StringUtils.contains(thr.getMessage(), "deadlock") || StringUtils.contains(thr.getMessage(), "try restarting transaction") || StringUtils.contains(thr.getMessage(),
                        "failed to resume the transaction")) {
                    if (attempt > 300) {
                        throw e;
                    }
                    int timeout = RandomUtils.nextInt(2000);
                    log.warn("Transaction rolled back. Restarting transaction.");
                    log.debug("Spleep for " + timeout);
                    log.debug("Restarting transaction: invocation=[" + invocation + "], attempt=[" + attempt + "]");
                    Thread.sleep(timeout);
                    attempt++;
                    return restart(invocation, attempt);
                } else {
                    throw e;
                }
            }
            return rval;
        }
    }
    

    另一方面,我严重怀疑这种解决方案的质量。 你能否详细说明并解释什么是最好的处理死锁的方法? 如何处理银行和企业应用程序中的死锁?


    Hibernate会话需要一个事务后写入一级缓存。 这使您可以对最后一个负责时刻进行后续更改,从而减少锁定采集间隔(即使在READ_COMMITTED隔离级别中也会发生)。

    这意味着您必须尽量减少所有交易时间,并且我可以推荐使用FlexyPool进行此类尝试。 您需要确保所有事务尽可能短,以减少锁定间隔,从而提高可伸缩性。

    锁定引入了串行操作,根据Amdahl定律,可扩展性与总串行操作分数成反比。

    我的建议是首先努力减少事务间隔。 索引将减少查询时间。 ORM可能会产生可怕的查询,所以确保您的集成测试能够验证预期的查询与实际执行的查询。

    像p6spy这样的工具对于定时查询非常方便,所以请确保您也使用它。

    当所有事务尽可能短并且仍然需要更多并发性时,您可以转向横向可伸缩性。 您可以先从同步主从复制策略开始,并将读取重定向到节点从属节点,同时保持写入事务的主节点。

    链接地址: http://www.djcxy.com/p/82069.html

    上一篇: Does Hibernate automatically restart transactions upon deadlocking?

    下一篇: RS client returns entity of null