Hibernate会在死锁时自动重启事务吗?

时间:2014-10-17 11:35:45

标签: java mysql spring hibernate transactions

有很多关于这个主题的文章:

我觉得最后接受的答案特别有趣:

  

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

这意味着我们永远不能阻止它们,而只能处理它们。真的吗?我想知道你是否可以防止在网上有1000名在线人员调用写入数据库操作的死锁。

谷歌搜索主题没有得到任何有趣的结果。我找到的只有一个(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;
    }
}

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

1 个答案:

答案 0 :(得分:4)

Hibernate会话需要transaction write-behind第一级缓存。这使您可以将更改推迟到最后一个负责时刻,从而减少锁定获取间隔(即使在READ_COMMITTED isolation level中也会发生)。

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

锁定引入了串行操作,根据Amdahl's law,可伸缩性与总串行操作分数成反比。

我的建议是先减少交易间隔。索引将减少查询时间。 ORM可能会生成糟糕的查询,因此请确保integration tests verify expected queries against actual executed ones

p6spy这样的工具可以非常方便地查询您的查询,因此请务必使用它。

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