关于此主题的文章很多:

  • Restarting transaction in MySQL after deadlock
  • Deadlock found when trying to get lock; try restarting transaction : @RetryTransaction
  • MySQL JDBC: Is there an option for automatic retry after InnoDB deadlock?
  • Working around MySQL error "Deadlock found when trying to get lock; try restarting transaction"
  • ...还有更多

  • 我发现最后一个被接受的答案特别有趣:



    那将意味着我们永远无法阻止他们,而只能与他们打交道。真的吗?我想知道您是否能够防止1000个在线调用写DB操作的人在网站上陷入僵局。

    对该主题进行谷歌搜索不会得到任何有趣的结果。我发现的只有一个(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 session 需要transaction write-behind一级缓存。这使您可以将更改推迟到最后一个负责任的时刻,从而减少了锁获取间隔(甚至在READ_COMMITTED isolation level中也会发生)。

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

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

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

    p6spy这样的工具非常方便地安排查询时间,因此请确保也使用它。

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

    关于java - 死锁时,Hibernate是否会自动重启事务?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26424184/

    10-11 10:44