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