更新数据库的时候不要这样做。你在干什么?请跟我来看看。此前,客户发来“XX,XXXXXXXX还有10万元未到账,请添加”之类的短信。我立马查了资料库找原因,然后回复了这么一句“开玩笑的”。虽然以前也出现过这样的问题,但都是小额资金,所以我手动添加到数据库中。这么大的资金我还是第一次遇到,于是我加快了翻数据库记录的步伐。发现用户的充值记录确实已经审核通过了,但是用户的可用资金却没有添加,这已经很奇怪了。然后再看代码,没发现逻辑上的问题,又让我失落了。再看日志,发现没有任何异常,嗯,感觉自己中招了。回想起来,这种情况并不常见,大多数时候程序没有这个,一切正常。太糟糕了,没有错误日志是最糟糕的错误。冷静一下,我觉得可能是事务有问题,因为对于资金表,同一用户的资金可能同时更新,我猜,存款记录插入存款和先取款记录表,资金表更新时被锁住,插入的记录在事务超时后没有回滚,所以我用这个方法来证明。STARTTRANSACTION;INSERTINTORecordVALUES(1,123);UPDATEmoneySETmoney=money+10;COMMIT;STARTTRANSACTION;UPDATEmoneySETmoney=money+100;COMMIT;通过手动控制事务锁,发现并不是我想的那样。然后我尝试了以下方法:STARTTRANSACTION;UPDATEmoneySETmoney=money+10;INSERTINTORecordVALUES(1,123);COMMIT;STARTTRANSACTION;UPDATEmoneySETmoney=money+100;COMMIT;发现两者的效果是一样的,都会回滚事务。这时,我的思想被禁锢了,我和同事一起讨论,看看他的想法是什么。经过一番思想斗争,同事还是给出了自己的想法,我深表赞同。MoneyUsermoneyUser=moneyUserMapper.selectByPrimaryKey(members.getUid());//冻结资金-取款金额moneyUser.setFrozenl(moneyUser.getFrozen().subtract(moneyTransfer.getount()));//可用资金+取款金额moneyUser.setTotaaymoney(moneyUser.getTotalpayey().add(moneyTransfer.getount()));this.moneyUserMapper.updateByPrimaryKey(moneyUser);这段代码并发时,获取moneyUser对象时,冻结资金和可用资金如果相加为0,那么在执行两个并发更新的时候,都执行,但是初始冻结资金和可用资金是一样的,这将导致一笔资金未被添加。调试的时候比较容易发现这个问题。哦,我的业力,这是一个多么大的问题,而且在资金方面,我很高兴它没有经常发生。但是我应该感恩还是不感恩?可能出现的次数多了,我就更容易反思,更容易找出问题的症结所在。那么如何解决问题呢?UPDATEmoneserSETfrozapital=frozpital-#{amount,jdbcType=DECIMAL},totaloney=totaloney+#{amount,jdbcType=DECIMAL}WHEREuid=#{uid,jdbcType=INTEGER}通过在sql语句中更新字段,而不是在Java类中,因为mysql本身会有办法处理这方面的。对于这个问题,之前的leader建议我尽量在更新数据的时候加入到sql语句中,而不是在class字段中处理。总结:这个问题,如果不注意,很容易出现这个问题。我一开始没有这样的意识。真的很难过!博文来源:http://blog.csdn.net/qing_gee/article/details/46233301
