社区编辑申请
注册/登录
数据库update时这样干,你就悲剧了
运维 数据库运维
数据库update时切忌这样干,这样干是什么?请随我来看看。

数据库update时切忌这样干,这样干是什么?请随我来看看。

早些时候,客户发来这样一段文字“XX的,XXXXXXXX有个10万没到账,帮加上去。”我马上动手查看数据库,寻找原因,随后回复了这样一句话“开玩笑吧”。虽然之前发生过类似这样的问题,但都是小额资金,就手动在数据库里加了,遇到这么大的资金还是头一次,于是我加紧翻看数据库记录的节奏。

我发现用户的入金记录的确已经是审核通过状态,而用户的可用资金却没有加上,这已经让人意外了。

接着我查看代码,并没有发现逻辑上的问题,这又让我感到迷茫。

再翻看日志,发现没有任何异常,好吧,感觉被设了局一样。

回头想想,这种情况并不多见,程序在多数情况下并没有这种情况,一切正常。这糟了,没有错误日志就是***的错误。

 

数据库update时这样干,你就悲剧了

静下心来,我想有可能是事务出现的问题,因为对于资金表,同一个用户的资金在同一个时间点是可能同时被更新的,我猜想,是入金记录先插入了出入金记录表,等到更新资金表的时候被锁住,事务超时后插入的记录没有回滚,于是我通过这样的方式来证明一下。

  1. START TRANSACTION
  2. INSERT INTO record VALUES(1,123); 
  3. UPDATE money SET money = money + 10; 
  4. COMMIT
  5.  
  6. START TRANSACTION
  7. UPDATE money SET money = money + 100; 
  8. COMMIT

通过手动控制事务锁,发现不是我想的那样。然后我又试了试下面这种方式:

 

  1. START TRANSACTION
  2. UPDATE money SET money = money + 10; 
  3. INSERT INTO record VALUES(1,123); 
  4. COMMIT
  5.  
  6. START TRANSACTION
  7. UPDATE money SET money = money + 100; 
  8. COMMIT

发现两者的效果是一样的,事务都会回滚。

这个时候,我的思路被禁锢了,我和同事讨论起来,看看他有什么想法,经过一番思想斗争后,果然同事还是给出了他的想法,我深感赞同。

 

  1. MoneyUser moneyUser = moneyUserMapper.selectByPrimaryKey(members.getUid()); 
  2.    // 冻结资金-出金金额 
  3.    moneyUser.setFrozenl(moneyUser.getFrozen().subtract(moneyTransfer.getount())); 
  4.    // 可用资金+出金金额 
  5.    moneyUser.setTotaaymoney(moneyUser.getTotalpayey().add(moneyTransfer.getount())); 
  6. this.moneyUserMapper.updateByPrimaryKey(moneyUser); 

这样的代码在出现并发的时候,获取moneyUser对象的时候,其中的冻结资金和可用资金加入都是0,那么两个并发在update的时候,两个都执行了,但是起初的冻结资金和可用资金相同,就会导致有一笔资金没有加上。

调试的时候更容易发现这个问题。OH,my 噶,真是个大问题,还出在资金的问题时,我真庆幸这个问题发生的频率不够高。不过我到底是应该庆幸还是不庆幸呢,也许次数发生的多起来的时候,我就更容易来反思来找出问题的症结所在。

那么问题怎么解决呢?

 

  1. UPDATE moneser 
  2.   SET 
  3.   frozapital = frozpital - #{amount,jdbcType=DECIMAL}, 
  4.   totaloney = totaloney + #{amount,jdbcType=DECIMAL
  5.   WHERE uid = #{uid,jdbcType=INTEGER

通过在sql语句中进行字段的更新操作,而不是在Java类中,因为mysql本身是会有这方面的处理方式的。

这个问题,之前领导有建议我在update数据的时候尽量在sql语句中加入,而不是类字段中做处理。

总结:这个问题,如果你不经意的话,很容易发生这个问题,我当初就没有这样的意识,真是可悲可叹!

博文出处:http://blog.csdn.net/qing_gee/article/details/46233301
 

责任编辑:Ophira 来源: CSDN博客
相关推荐

2011-07-18 16:56:12

Sqlite数据库Update语句

2011-08-24 13:10:48

MongoDBUpdate

2011-06-30 15:26:28

Update数据库

2013-11-12 14:43:43

MySQL数据库

2020-08-10 07:52:30

MySQL数据库

2011-05-18 11:08:34

2011-08-11 13:19:17

MySQLupdatedelete

2021-09-15 09:51:36

2011-08-02 14:09:53

Update语句OracleSQL Server

2017-11-02 21:02:11

数据库数据库的管理字段长度

2021-11-09 06:42:51

2018-01-03 09:09:09

数据库速度技巧

2020-06-03 17:10:40

MySQLupdate数据库

2019-03-21 14:00:05

MySQLUpdate数据库

2010-09-06 09:11:24

2020-08-05 16:44:55

运维架构技术

2018-04-24 18:23:02

数据库误删

2019-09-16 09:03:11

数据库SQLMySQL

2021-03-19 07:40:22

缓存数据库日志

2021-09-15 06:21:36

编辑推荐

Oracle免费的便捷Web应用开发框架二则从携程系统瘫痪,看国内企业数据管理乱象数据库update时这样干,你就悲剧了影响数据检索效率的几个因素携程事件反思:是该重视数据库灾备了!
我收藏的内容
点赞
收藏

51CTO技术栈公众号