mysql 基礎數據併發插入導致表鎖死

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

  哈哈,這是不得已的辦法。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章