这个话题已经有很多人写过了:
- 在死锁后重启MySQL事务
- 当尝试获取锁时发现死锁; 尝试重新启动事务:@RetryTransaction
- MySQL JDBC:InnoDB死锁后自动重试的选项是否存在?
- 解决MySQL错误“尝试获取锁时发现死锁; 尝试重新启动事务”
- ... 还有更多
我特别感兴趣的是最后一个被接受的答案:
如果您使用InnoDB或任何行级事务RDBMS,则可能会发生死锁,即使在完全正常的情况下也是如此。大表格,大写作和长事务块通常会增加死锁发生的可能性。在您的情况下,这可能是这些因素的结合。
这意味着我们永远无法防止死锁,只能处理它们。这是真的吗? 我想知道是否可以防止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;
}
}
另一方面,我严重怀疑这种解决方案的质量。能否详细说明并解释如何最好地处理死锁?在银行和企业应用程序中如何处理死锁?