码迷,mamicode.com
首页 > 数据库 > 详细

MySQL 出现死锁的分析和解决方案

时间:2015-07-16 14:30:20      阅读:218      评论:0      收藏:0      [点我收藏+]

标签:

异常日志

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

这样就能解决死锁问题

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


MySQL 出现死锁的分析和解决方案

标签:

原文地址:http://my.oschina.net/u/1244507/blog/479257

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!