MySQL 出現死鎖的分析和解決方案

異常日誌mysql

### Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transactionsql

### The error may involve defaultParameterMapapp

### The error occurred while setting parametersspa

### SQL: UPDATE t_withdraw_apply SET last_apply_time=? WHERE user_id = ? AND state = 0rest

### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction日誌

; SQL []; Deadlock found when trying to get lock; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction事務

很顯然,出現死鎖的SQL語句是UPDATE t_withdraw_apply SET last_apply_time=? WHERE user_id = ? AND state = 0get

再看業務邏輯it

int i = withdrawApplyDAO.add(apply);io

    if(i == 1) {

      //獲取該用戶最先的待提現申請時間

      Timestamp earlierTime = withdrawApplyDAO.getEarlierApplyTime(userId);

      withdrawApplyDAO.updateEarlierApplyTime(userId,earlierTime);//更新冗餘字段

      //扣除帳戶餘額,而後寫入gold_log日誌

      int j = userDAO.updateUserGold(0-amount, userId);

......

那麼爲何會出現死鎖呢?


原來是這樣的,用戶點擊過快同時提交了兩次提現申請

那麼就會開啓兩個事務

事務1 插入一條apply

事務2 也插入一條apply

事務1 執行更新 updateEarlierApplyTime ,因爲事務2插入的數據也須要更新,因此這個時候 事務1須要等待事務2提交後才能執行

事務2 頁執行更新 updateEarlierApplyTime ,一樣須要更新事務1插入的輸入,也須要等地事務1完成才能繼續執行,這樣就出現了死鎖


怎麼解決這個問題呢?

首先出現這個問題的緣由是事務1更新的數據包含了事務2插入的數據,事務2更新也包含了事務1插入的數據,那麼咱們能夠讓代碼改成

 withdrawApplyDAO.updateEarlierApplyTime(userId,earlierTime);//更新冗餘字段

 withdrawApplyDAO.add(apply);

這樣就能解決死鎖問題

其次,出現這樣的問題是用戶重複提交致使的,因此應該作重複提交的限制,

相關文章
相關標籤/搜索