最近在进行接口优化进行并发测试时,发现有全部正常执行了但是返回的结果却总是缺失不完整,查看log日志发现报了 [ERROR] org.hibernate.util.JDBCExceptionReporter - Deadlock found when trying to get lock; try restarting transaction 错误。
尝试了以下几种方式来解决这个问题。
1.synchronized修饰方法
将synchronized关键字加到post接口被请求处,此方法可以有效避免数据库中表锁死,但是会导致数据返回时间过长。原因是该关键字加载接口被请求处,同一时刻最多只有一个线程执行这段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。所以时间会非常慢。
2.synchronized修饰调用数据库处
为了避免数据会全部被阻塞在post接口被请求处,先将接口请求数据执行请求放进来执行相关业务逻辑,在数据存储时进行synchronized修饰,通过并发测试发现执行耗时会有所减少,但是依然会导致数据库表死锁,
3.spring-retry。
MySQL的InnoDB引擎具有行级锁定功能,即使您的代码正在插入或更新单个行(尤其是要更新的表上有多个索引),也可能导致死锁。最好的选择是围绕它设计代码,以便在由于死锁而失败的情况下重试事务。
@Retryable(maxAttempts = 4, backoff = @Backoff(delay = 500))
public void doSomethingWithMysql() {
consumerTransactionTemplate.execute(
new TransactionCallbackWithoutResult(){
@Override
protected void doInTransactionWithoutResult(
TransactionStatus status)
{
process();
}
});
}
如果出现任何异常,它将以500ms的退避策略重试(调用)doSomethingWithMysql()方法的4倍.
4.删除该更新数据操作,改为插入
哈哈,这是不得已的办法。