最近在進行接口優化進行併發測試時,發現有全部正常執行了但是返回的結果卻總是缺失不完整,查看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.刪除該更新數據操作,改爲插入
哈哈,這是不得已的辦法。