`

一个多用户并发引起的丢失更新的实例

阅读更多
查询操作不用做事务处理或者不用加锁,以前一直比较同意,今天遇到一个实际的问题,原来这种想法是错误的.

项目中遇到一个用户资金扣除出错的问题:
系统采用了quartz来做定时任务的处理,在某个时间点,自动对用户购买方案进行扣款,通过对日志的跟踪发现:当用户购买了多个方案时,有时用户可用资金会出错。

要实现的功能:
查询用户的可用资金,然后扣款。
假设用户w当前可用资金为1000元,应该执行两次扣款,第一次100,第二次50,用户w正确的余额应该是850。

出错原因:
扣款前要先查询用户当前的可用金额,然后再扣款.
通过日志发现,线程a查询完用户w的可用金额为1000元后,暂停了执行扣款的操作。
然后线程b开始执行,线程b查询用户w的可用金额为1000元,然后扣款50,更新DB,这时用户w余额是950。
然后,线程a在1000的基础上扣款100,更新DB,这时用户w的最终余额是900元。显而易见,用户w的最终余额是错误的。

结论:查询操作不用做事务处理或者说不用加锁是错误的。

其实这是一个丢失更新的典型的场景,但在实际中真实地遇到它,还是让人很兴奋啊.
分享到:
评论
14 楼 charles751 2007-12-26  
第一贴就成新手贴,可悲啊.
看来我水平有限啊,还是到serverside去混吧
13 楼 xiangzhouwang 2007-12-26  
控制下加锁级别
12 楼 soci 2007-12-25  
多线程共享资源啊 和数据库没啥关系  和俩线程访问同一个实例是一回事
11 楼 hocus 2007-12-25  
查询和更新应该做到一个事务控制的方法里。
该方法会被多个线程调用,所以该方法需要同步控制。
10 楼 movingboy 2007-12-25  
最基本的事务处理问题啊~~~
“查询操作不用做事务处理或者不用加锁”是指不需要对查询出来的数据进行更新(包括删除),自然不需要进行事务管理了。楼主的情况很明显不同,当然需要事务管理了。建议楼主再读点数据库基础方面的书
9 楼 charles751 2007-12-25  
ideafrog 写道
你的数据库是oracle吗?

不同的数据库有不同的锁机制。你这样说,根本就是在乱扯。虽然有那么点道理,但是与问题本质没有关系


能解释下您说的本质吗
8 楼 ideafrog 2007-12-25  
你的数据库是oracle吗?

不同的数据库有不同的锁机制。你这样说,根本就是在乱扯。虽然有那么点道理,但是与问题本质没有关系
7 楼 charles751 2007-12-25  
ddandyy 写道
所谓的查询  是指整个事务里只有一个查询


看来大家的看法比较一致啊.
我这个场景中,查询只是事务的一部分而已.

这个查询方法在dao层中,事务由service方法做处理
6 楼 ddandyy 2007-12-25  
所谓的查询  是指整个事务里只有一个查询
5 楼 charles751 2007-12-25  
WorkingHard?! 写道
关键是你更新的策略问题,你在进行更新的时候逻辑是怎么写的~

如果是查询出来余额判断后执行更新操作,那么你这个逻辑的本身也是属于更新的一部分,方法类似

public void updateAccount(***){
   double account  =  queryAccout();
   XXDAO.update(XXX);
}

事务的设置可以用声明式事务对该方法进行设定 或者 自己手动控制事务



同意.

投入门贴的朋友们,你们都遇到过这种场景吗?表示怀疑
4 楼 抛出异常的爱 2007-12-25  
脏读...锁机制存在的主要原因之一
3 楼 WorkingHard?! 2007-12-25  
关键是你更新的策略问题,你在进行更新的时候逻辑是怎么写的~

如果是查询出来余额判断后执行更新操作,那么你这个逻辑的本身也是属于更新的一部分,方法类似

public void updateAccount(***){
   double account  =  queryAccout();
   XXDAO.update(XXX);
}

事务的设置可以用声明式事务对该方法进行设定 或者 自己手动控制事务
2 楼 sorphi 2007-12-25  
你这里的场景:查询操作只是一个完整事务的一部分

可别从一个极端到另外一个极端
1 楼 daquan198163 2007-12-25  
乐观锁是用来解决这个问题的

相关推荐

    Java并发编程实战

    本书深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册。书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及验证线程安全的规则...

    Java高并发高性能分布式框架从无到有微服务架构设计.doc

    MapDB: mapdb是一个内嵌的纯java的数据库,提供了并发的HashMap、TreeMap、Queue,可以基 于堆外或者磁盘来存储数据高并发-应用缓存堆外缓存 即缓存数据存储在堆外内存,可以减少GC暂停时间(堆对象转移到堆外,GC...

    Java高并发高性能分布式框架从无到有微服务架构设计(1).doc

    因为高并发 的时候是有很多用户在访问,导致出现系统数据不正确、丢失数据现象,所以想到 的是用队列解决,其实队列解决的方式也可以处理,比如我们在竞拍商品、转发评论微博 或者是秒杀商品等,同一时间访问量特别大,...

    net学习笔记及其他代码应用

    然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中...

    数据库系统概论第四版答案

    安全性、多用户并发控制、故障恢复等,都由 DBMS 执行。总之,使用数据库系统的优点 是很多的,既便于数据的集中管理,控制数据冗余,提高数据的利用率和一致性,又有利于 应用程序的开发和维护。读者可以在自己今后...

    java面试题

    答:Servlet与CGI的区别在于Servlet处于服务器进程中,它通过多线程方式允许其service方法,一个实例可以服务于多个请求,并且其实例一般不会被销毁,而CGI对每个请求都产生新的进程,服务完后就销毁,所以效率上...

    超详细mongodb教程.zip

    所谓的独立性是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个事务修 改,只要另外一个事务未提交,它所访问的数据就不受未提交事务的影响。 比如现有有个交易是从A账户转100元至B账户,在...

    asp.net知识库

    制作一个简单的多页Tab功能 一完美的关于请求的目录不存在而需要url重写的解决方案! 在C#中实现MSN消息框的功能 XmlHttp实现无刷新三联动ListBox 鼠标放在一个连接上,会显示图片(类似tooltip) 使用microsoft.web.ui...

    优考试局域网考试系统 v4.2.2 标准版.zip

    在创建一个新试卷时,总是希望可以从题库中的指定分类中随机选择一定数量的试题加到试卷中,这即可以快速生成一个新的试卷,也可以让试卷在题库中平均的选择试题,在微课的实例中,你可以利用该功能,快速的从章节题库...

    精通SQL 结构化查询语言详解

    全书共包括大小实例317个,突出了速学速查的特色。《精通SQ:结构化查询语言详解》内容丰富,讲解通俗易懂,具有很强的实用性和可操作性。 目录 第1章 数据库与SQL基础  1.1 数据库的基本概念  1.1.1 数据库的...

    citrix 中文管理操作手册

    向一个或多个用户发送消息 106 控制 XenApp 中的客户端连接 106 XenApp 策略 106 应用程序发布 106 终端服务配置 106 Active Directory 106 阻止特定客户端连接类型 107 配置连接访问控制 107 指定连接限制 107 限制...

    SQLServer2008查询性能优化 2/2

    在开发代码的同时,如果你花费时间和精力来开发一个性能故障排错的方法。那么你就能避免这种情况——至少可以快速而有效地做出反应。《SQL Server 2008查询性能优化》指出的性能要点之一是数据库随着用户和数据的日...

    SQLServer2008查询性能优化 1/2

    在开发代码的同时,如果你花费时间和精力来开发一个性能故障排错的方法。那么你就能避免这种情况——至少可以快速而有效地做出反应。《SQL Server 2008查询性能优化》指出的性能要点之一是数据库随着用户和数据的日...

    Oracle 9i&10g编程艺术:深入数据库体系结构(全本)含脚本

    目录回到顶部↑第1章 开发成功的Oracle应用 1 1.1 我的方法 2 1.2 黑盒方法 4 ...15.2.4 多用户问题 697 15.2.5 外部表小结 698 15.3 平面文件卸载 698 15.4 数据泵卸载 708 15.5 小结 710 索引 711

    OCPOCA认证考试指南全册:Oracle Database 11g(1Z0-051,1Z0-052,1Z0-053)--详细书签版(第1/2部分)

    2.4.2 使用DBCA创建一个数据库 63 2.4.3 DBCA 创建的脚本和其他文件 67 2.4.4 DBCA的其他功能 73 2.5 本章知识点回顾 74 2.6 自测题 75 2.7 自测题答案 78 第3章 实例管理 81 3.1 设置数据库初始化参数 82 ...

    OCPOCA认证考试指南全册:Oracle Database 11g(1Z0-051,1Z0-052,1Z0-053)--详细书签版(第2/2部分)

    2.4.2 使用DBCA创建一个数据库 63 2.4.3 DBCA 创建的脚本和其他文件 67 2.4.4 DBCA的其他功能 73 2.5 本章知识点回顾 74 2.6 自测题 75 2.7 自测题答案 78 第3章 实例管理 81 3.1 设置数据库初始化参数 82 ...

    TCP_IP详解卷1

    13.3.1 加入一个多播组 136 13.3.2 IGMP报告和查询 137 13.3.3 实现细节 137 13.3.4 生存时间字段 138 13.3.5 所有主机组 138 13.4 一个例子 138 13.5 小结 141 第14章 DNS:域名系统 142 14.1 引言 142 14.2 DNS...

Global site tag (gtag.js) - Google Analytics