Analysis and Solution of Deadlock in MySQL

Abstract: The company has a cash withdrawal business. This cash withdrawal business is more complicated. There are additions and updates, so transactions are added, but a deadlock exception occurs after running for a period of time. By checking the log, I finally analyzed the reason and solved the problem. It is impossible to write this, so that people can avoid detours later.

exception log

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

### The error may involve defaultParameterMap

### The error occurred while setting parameters

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

### 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

Obviously, the deadlock SQL statement is UPDATE t_withdraw_apply SET last_apply_time=? WHERE user_id = ? AND state = 0

Look at the business logic again

int i = withdrawApplyDAO.add(apply);

    if(i == 1) {

      //Get the earliest application time of the user to be withdrawn

      Timestamp earlierTime = withdrawApplyDAO.getEarlierApplyTime(userId);

      withdrawApplyDAO.updateEarlierApplyTime(userId,earlierTime);//Update redundant fields

      //Deduct the account balance, and then write to the gold_log log

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

......

So why does deadlock occur?


It turns out that the user clicked too quickly and submitted two withdrawal applications at the same time

Then two transactions will be started

Transaction 1 inserts an apply

Transaction 2 also inserts an apply

Transaction 1 executes  updateEarlierApplyTime. Since the data inserted by transaction 2 also needs to be updated, transaction 1 needs to wait for transaction 2 to commit before executing.

The transaction 2 page performs update  updateEarlierApplyTime, and also needs to update the input inserted by transaction 1, and also needs to wait for transaction 1 to complete before continuing to execute, so a deadlock occurs


How to solve this problem?

The first reason for this problem is that the data updated by transaction 1 contains the data inserted by transaction 2, and the update of transaction 2 also contains the data inserted by transaction 1, then we can change the code to

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

 withdrawApplyDAO.add(apply);

这样就能解决死锁问题

其次,出现这样的问题是用户重复提交导致的,所以应该做重复提交的限制,



https://my.oschina.net/u/1244507/blog/479257



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325645023&siteId=291194637