`

遭遇数据库并发问题

阅读更多
最近碰到一个数据库并发的问题, 觉得是一个很有意义的经验教训, 备忘一下.
大致过程是这样的:
在一次迭代发布之后, 用户反馈了一个问题: 虚拟商品交易成功, 但是买家没有收到卡密.而在日志中跟踪该笔交易, 正好有一个超时情况, 日志中打印出了程序执行的完整路径, 也就是说整个交易完全没有问题. 当时百思不得其解. 怀疑数据库出了问题. 又过了一天, 用户反映了同样的问题, 对比一下本次发布的代码修改, 里面有一个是关于sql的优化, 比较修改前后的代码, 终于找到了问题的罪魁祸首:原来是在sql上出现了问题.
最开始正确的sql:
update table set status =#newStatus#, trade_id = #tradeId#, buyer_id = #buyer_id# where id in (
	select * from (
		select id from table 
		where item_id = #itemId# 
		and status = #initStatus#
		order by id 
	) where rownum <= #count#
) and status = #initStatus#

这句sql的意思是, 一个商品下面有多个虚拟物品(比如游戏币, 充值卡), 一个买家购买了该商品的多个虚拟物品, 此时应该将虚拟物品的状态设置为已购买状态, 因为这些虚拟物品会有多个人购买, 为了避免同一个虚拟物品被不同的人同时购买, 需要对要购买的虚拟物品排序, 然后从中获取要购买的数量, 最后更新状态.
修改后有问题的sql是这样:
update table set status =#soldStatus#, trade_id = #tradeId#, buyer_id = #buyer_id# where id in (
	select * from (
		select id from table 
		where item_id = #itemId# 
		and status = #initStatus#
		order by id 
	) where rownum <= #count#
)

当时咨询dba, 认为在里面已经判断了状态, 外层sql的状态判断显得多余, 建议去掉.

虽然整个sql操作过程也是在事务中执行. 但是依然无法避免并发的出现, 经过分析, 基本上可以还原出问题的场景:
因为更新状态实际上分为两步, 首先要查出数据, 接着再更新. 当两个人同时购买同一个商品时. 如果两人同时查出同一批数据, 一人先更新, 退出事务(此时这批数据的状态已经发生改变), 接着另外一个人再次更新, 如果此时更新没有判断这批数据当前的状态(也就是做乐观锁), 那么就会覆盖前更新者的数据, 导致前一个没有获得最终购买的虚拟物品.
而外层的状态判断相当于对执行的sql加了一个乐观锁, 如果查询得到的那批数据被另一个请求更新, 则在更新状态的数量将与请求的数量不一致, 导致该次更新失败.
分享到:
评论
4 楼 macrochen 2010-06-28  
zyf30222 写道
有点不明白,我举个例子吧!
某个物品总共有5个,A想买5,B也想买5,这时候,并发的结果是什么呢?

我的猜测是:
A的确买了5,B没有买到,总共卖出也为5;(A的先处理)

想知道最后结果是什么呢?

A买了5个, 首先要找出这5个, 然后B也要买5个, 也从数据库中找5个, 因为这个动作是同时进行的, 所以A, B找的是相同的5个, 但是更新的时候A先更新, 这是可以看到5条更新记录, B后更新5条记录, 此时将覆盖A的更新记录, 如果有一个字段做锁在A更新的时候同时更新锁字段, B再次更新因为所字段已更新, 导致更新记录数为0, 此时就可以判断更新失败
3 楼 zyf30222 2010-06-28  
有点不明白,我举个例子吧!
某个物品总共有5个,A想买5,B也想买5,这时候,并发的结果是什么呢?

我的猜测是:
A的确买了5,B没有买到,总共卖出也为5;(A的先处理)

想知道最后结果是什么呢?
2 楼 macrochen 2010-06-26  
zyf30222 写道
业务上碰到这个怎么处理的,前台提示?
后台碰到这种情况,update后面,是否还有一个是否执行成功(更新的条数),但是这个条数不好确认吧。

前台不会察觉有问题, 但是用户会发现他的购买数量有问题
因为两次更新都是成功的, 因此对更新条数的检查也是没有问题的.
1 楼 zyf30222 2010-06-25  
业务上碰到这个怎么处理的,前台提示?
后台碰到这种情况,update后面,是否还有一个是否执行成功(更新的条数),但是这个条数不好确认吧。

相关推荐

    数据库系统概论PPT第1章-PPT幻灯片.ppt

    数据库在运行过程中可能会遭遇各种故障,如硬件故障、软件故障或操作失误等,数据库恢复技术的目的是在这些异常情况下能够将数据恢复到一个一致的、正确的状态。而并发控制是为了在多用户环境下,合理地管理对数据库...

    阿里巴巴大并发插入优化案例

    阿里巴巴大并发插入优化案例充分展示了在面临高并发场景时,通过深入理解并优化数据库底层存储结构和索引策略,可以有效解决性能瓶颈问题。尤其是针对ASSM位图结构的精细控制,以及索引设计的创新思路,为其他企业...

    数据库安全保护数据库安全保护.ppt

    - 当数据库遭遇故障或破坏时,数据库恢复技术能够将系统恢复到一致状态。这通常依赖于事务日志和备份,以便在系统崩溃后重新执行未完成的事务或回滚已完成的不一致事务。 5. **操作系统安全性**: - 安全的操作...

    数据库填空题

    6. 故障类型:数据库可能遭遇事务故障、系统故障、介质故障和计算机病毒等问题。介质故障通常指硬件损坏,更难以恢复。 7. 并发控制:采用封锁机制来管理并发操作,包括共享锁(允许多个事务同时读取数据)和排它锁...

    数据库原理与设计课件:第8章 数据库恢复技术.ppt

    数据库镜像则是通过创建数据库的实时副本,当主数据库出现问题时,可以立即切换到镜像数据库,保证服务连续性。 SQL Server的数据恢复机制体现了上述理论,它提供了多种恢复模型,如简单恢复模型、完整恢复模型和大...

    oracle数据库备份与恢复技术

    3. **维护控制文件的多个并发备份**:确保即使其中一个控制文件损坏也能迅速恢复。 4. **时常备份物理数据文件**:建议定期备份数据文件,并将备份文件存放在安全的位置。 #### 五、备份与恢复操作 ##### 5.1 常见...

    数据库系统安全.ppt

    - 数据库可能会遭遇事务内部故障、系统故障、介质故障甚至恶意攻击。故障恢复机制旨在快速恢复系统到正常状态,确保数据的完整性和一致性。 - 日志记录和备份:通过记录事务操作日志和定期备份,可以在系统崩溃后...

    数据库原理考试题库.docx

    6. **数据库故障**:数据库可能遭遇事务故障、系统故障、介质故障和计算机病毒等,需要有相应的恢复策略。 7. **并发控制**:通过封锁机制防止并发操作导致的数据不一致,封锁分为共享锁(读锁)和排它锁(写锁)。...

    高并发Java服务器设计研究.pdf

    当前,为解决高并发问题,有多种手段可采用。硬件升级是最直观的方法,但成本较高且不是根本解决方案。除了硬件升级,提升服务器的并发能力还可以通过参数调优等软件优化手段进行,但最为关键的还是对服务器架构的...

    高并发Web系统的设计与应用.pdf

    在当前互联网环境中,尤其对于提供公共服务如高考分数查询的系统,高并发问题显得尤为重要,因为这类服务往往会在短时间内面临成千上万的访问请求。 在设计高并发Web系统时,首先要考虑的是软硬件架构的选择。文章...

    数据库期末考试复习题及答案-填空简答.docx

    15. **故障类型**:数据库系统可能遭遇事务故障、系统故障和介质故障,需要有恢复机制来应对这些故障。 这些知识点涵盖了数据库的基础理论、SQL语法、数据模型、关系数据库设计、事务处理和并发控制等多个方面,是...

    065-066 网络游戏数据库技术(1).ppt

    但随着游戏的规模和复杂度不断增加,关系模型可能会遭遇性能瓶颈,因此对数据库的优化就显得尤为重要。例如,使用索引来加速数据检索,合理设计表结构来优化存储空间,使用缓存机制来减少数据库的压力,以及采用...

    数据库原理与应用总复习.pdf

    19. 数据库系统可能遭遇事务故障、系统故障、介质故障和计算机病毒等,备份策略包括完全备份、事务日志备份和增量备份。 20. 备份操作可在线或离线进行,封锁类型包括排他锁和共享锁,控制并发访问。 以上内容详尽...

    2021年mysql数据库笔试题一.docx

    2. 数据库可能遭遇**事务失败**、**系统崩溃**和**磁盘故障**。 3. 视图是从**基本表**中导出的虚表,仅存储其**定义**,不存储**具体数据**。 4. 关系操作具有**集合操作**的特点。 **简答题部分**: 1. 创建表...

    Oracle第11章数据库备份与恢复.pptx

    热备份允许在不影响数据库服务的情况下进行,但冷备份更为安全,因为它不会引入潜在的并发问题。 - 逻辑备份则通过Oracle的导出工具(如Expdp, Export)将数据抽取到二进制文件中,便于在需要时导入数据库。 ...

    Oracle数据库备份与恢复 (1).pdf

    数据库可能会遭遇各种故障,包括事务故障、系统故障和介质故障,每种故障都需要采取不同的恢复策略。 1. **事务故障**:当某个事务在执行过程中突然中断,系统需要通过回滚该事务,即撤销其对数据库的所有改动,以...

    2009系统架构师大会PPT:徐景春:企业级开源数据库灾备体系

    2. **数据库机器众多**:为了支持海量数据和高并发访问,通常会部署多台数据库服务器。 3. **多地部署**:为了提高可用性和容灾能力,数据库不仅在本地数据中心部署,也会在远程数据中心进行部署。 4. **多种数据库...

    MySQL数据恢复的三种常用的方式

    MySQL 数据恢复是数据库管理中的一项重要任务,尤其是在遭遇意外数据丢失、硬件故障或软件错误时。以下是三种常用的数据恢复方式的详细说明: 1. **通过表备份的方式**: 当数据表因各种原因如误删除、软件故障或...

    解决当MySQL数据库遇到Syn Flooding问题

    尽管上述调整能提升数据库的抗压能力,但解决根本问题需要分析连接压力的来源和为何需要大量并发连接。可能的解决方案包括: - 使用缓存层,如Redis,作为数据库前端,以缓冲突如其来的连接请求,降低对数据库的压力...

    序列号生成buge修改---超时问题,999溢出异常

    1. **并发处理**:当大量请求同时涌入,如果序列号生成逻辑没有做好并发控制,可能会导致数据库锁竞争,从而引发超时。 2. **数据库查询效率**:如果序列号依赖于数据库自增字段,频繁的读写操作可能导致数据库响应...

Global site tag (gtag.js) - Google Analytics