`

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

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

项目中遇到一个用户资金扣除出错的问题:
系统采用了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  
乐观锁是用来解决这个问题的

相关推荐

    三份数据库并发处理方案

    数据库并发处理是数据库系统中的重要概念,特别是在多用户环境下,多个事务同时访问和修改数据库时,如何保证数据的一致性、完整性和隔离性是至关重要的。本方案将深入探讨并发控制技术,确保在高并发场景下数据库的...

    《数据库原理》并发操作、串行调度

    并发控制是指在多个用户并发地存取数据库时,避免数据不一致性的技术。其核心问题是对并发操作进行正确的调度,以保证数据的一致性。并发控制的主要技术是封锁和有效性确认。 二、并发操作可能会产生哪几类数据不...

    多线程的TCP和UDP通讯实例

    总结起来,多线程的TCP和UDP通讯实例是一个深入学习网络编程的好项目,它涵盖了网络连接、多线程编程和数据传输的基本概念。通过实际操作,开发者不仅可以理解TCP和UDP的区别,还能掌握如何在C++环境中实现多线程...

    基于SQL Server 2000的实用并发控制技术.pdf

    1. SQL Server 2000并发控制机制:SQL Server 2000提供了复杂的并发控制机制,支持多用户并发访问数据。该机制的关键在于确保事务的原子性、一致性、隔离性和持久性,保障数据库数据的完整性和一致性。 2. 事务处理...

    redis百万并发访问数据库测试需要的jar包

    7. **Cluster集群**:当单个Redis实例无法满足高并发需求时,可以搭建Redis Cluster,将数据分布在多个节点上,实现数据的自动分片,提高系统的可用性和扩展性。 8. **Jedis**:Jedis是Java语言的Redis客户端库,...

    《计算机网络与通信编程典型实例解析》实例1、2

    压缩包子文件的文件名称列表只包含了一个条目——《计算机网络与通信编程典型实例解析》实例1、2,这可能意味着压缩包中包含了这两个实例的完整代码和相关的解释文档。读者可以下载并运行这些代码,观察其运行效果,...

    socket编程实例

    在多用户聊天场景中,服务器需要维护一个用户列表,记录每个在线用户对应的Socket。当一个客户端发送消息时,服务器会遍历这个列表,将消息通过对应的Socket发送给每个用户。为了实现高效,通常会采用异步I/O或者...

    20个VC++网络相关的源代码实例

    这个压缩包文件"20个VC++网络相关的源代码实例"显然是一个资源集合,为开发者提供了学习和实践VC++网络编程的宝贵材料。下面,我们将详细探讨这些源代码实例可能涵盖的知识点。 首先,VC++中的网络编程主要依赖于...

    软件工程实例订票系统

    对于订票系统,我们尤其要关注并发处理能力,因为大量用户可能会在同一时间进行购票操作,系统必须能够正确处理这些并发请求,避免数据冲突和丢失。 最后,系统的维护和更新是持续性的任务。随着业务的发展和技术的...

    你想要Android数据库操作精华(安全、并发、单例等)

    在单例模式下操作数据库,可以避免多个实例间的冲突,确保全局只有一个数据库访问入口,从而更好地控制并发。 单例模式是一种设计模式,它保证一个类只有一个实例,并提供一个全局访问点。在数据库操作中,使用单例...

    数据库开发设计实例 方案 案例 实例

    案例中的文件名暗示了这是一个基于Web的数据库应用实例。例如,`index.jsp`通常作为网站的主页,`register.jsp`用于用户注册,`login.jsp`处理用户登录,`Manager_index.jsp`可能是管理员主界面。这些页面与后端...

    互联网高并发+高可用+海量用户架构实践

    ### 互联网高并发+高可用+海量用户架构实践 #### 一、单点系统可用性架构与优化方向 **互联网架构师的任务**:确保架构设计紧密贴合业务需求,任何脱离实际业务需求的设计都难以发挥最大价值。 **互联网架构的...

    数据库编程技术与实例

    8. **并发控制与锁机制**:在多用户环境下,数据库需要管理多个事务的并发执行,防止数据不一致。锁机制是实现并发控制的一种方法,包括共享锁(读锁)和独占锁(写锁)。 9. **安全性与权限管理**:通过用户账户、...

    数据库实例

    一个数据库实例是数据库管理系统(DBMS)运行的具体化表现,它为用户提供了一个交互环境来创建、查询、更新和管理数据库。在"上位"和"低层"的语境下,这可能指的是数据库实例在不同层次的系统架构中的应用,例如从应用...

    数据库系统实例

    并发控制是多用户环境下数据库系统的关键特性。SQL Server采用事务和锁机制来确保数据的一致性。在本系统中,当多个用户同时操作报价时,事务的ACID属性(原子性、一致性、隔离性和持久性)确保了操作的正确性。同时...

    网络并发文件.rar

    这在并发文件传输中尤为重要,因为它可以同时处理多个客户端的连接请求,实现多用户并发访问。 接下来,QThread是QT中的多线程支持类。在多线程环境中,QThread允许我们将任务分配到不同的线程,以提高程序执行效率...

    一个基础的Delphi远程控制模型实例..rar

    本压缩包“一个基础的Delphi远程控制模型实例”提供了一个用Delphi实现的简单远程控制系统的示例,对于学习Delphi编程以及网络通信技术具有很高的参考价值。 远程控制模型的核心在于客户端和服务器端的通信机制。在...

    乘风多用户计数器 mssql版 v4.7.zip

    对于计算机科学及相关专业的毕业生而言,乘风多用户计数器 MSSQL版 V4.7是一个有价值的项目实例。它涵盖了数据库管理、多线程编程、用户交互等多个关键知识点,是实践数据库应用和Web开发技能的理想平台。通过分析和...

    多线程并发同步(爸爸妈妈苹果橘子问题,有界面)

    在IT领域,多线程并发同步是一个至关重要的概念,尤其在设计高性能、高效率的应用程序时。本项目通过一个生动的实例——“爸爸妈妈苹果橘子问题”来演示这一概念,结合了VC++(Visual C++)环境下的图形化实现,使得...

Global site tag (gtag.js) - Google Analytics