mysql出现死锁的结果_MySQL 出现死锁的分析和解决方案

异常日志

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

很显然,出现死锁的SQL语句是UPDATE t_withdraw_apply SET last_apply_time=? WHERE user_id = ? AND state = 0

再看业务逻辑

int i = withdrawApplyDAO.add(apply);

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);

这样就能解决死锁问题

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值