【发布时间】:2014-12-12 23:42:26
【问题描述】:
关于这个话题已经有很多文章了:
- 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"
- ...更多
我发现最后一个接受的答案特别有趣:
如果您使用 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;
}
}
另一方面,我严重怀疑这种解决方案的质量。您能否详细说明并解释死锁的最佳处理方式是什么?如何处理银行和企业应用程序中的死锁?
【问题讨论】:
-
您对这样的解决方案有什么疑问?它是 AOP 捕获异常并在某些情况下重试。虽然 300 次重试可能有点陡峭。 Spring 也有一个小项目,Spring Retry(也被 Spring Integration 和 Spring Batch 用于这种逻辑)。
-
这真的是尝试重启交易的最佳方式吗?难道真的没有办法在重负载数据库中防止它们吗?
-
重试有什么问题。您可以尝试通过隔离数据库来阻止它们,但这样您的应用程序就会爬网......
标签: java mysql spring hibernate transactions