完整电商项目--(八)商品订单模块(2): mysql乐观锁与 事务隔离级别

MySQL 事务与锁:从超卖到零错误,我用事务隔离级别 + 锁机制根治了电商库存问题 如何通过实例来解锁,本文通过库存的例子,深入浅出的分析了什么事锁,什么是事务,并如何解决死锁问题,通过事务处理来解决并发导致的脏数据,幻读,超卖问题以及事务优化的经验总结。 阅读详情

什么是并发?

前情提要:

  • 上节事务解决的问题是,多个逻辑任务之间是 必须同时成功,或者同时失败的(比如创建订单对象与创建订单商品对象)

并发场景

  • 当库存有限,但是让同事有多个用户购买,会发生并发问题。
  • 计入商品a有 1件商品, a,b用户同时购买,读取数据库中的商品数量时都是1 ! ,结果二人都创建订单成功,但是:数据库中很明显只有一件商品,不够卖给两个人。这就是接着要解决的并发问题。

解决并发的方式:

(1) 排队

  • 本质上还是一个一个的处理请求,但是不用让用户去感受到他在等别人执行完之后,才去执行他的,需要使用到 celery。 开启只有一个进程的celery,一个订单一个订单请求的在后台排队处理。

(2) 利用 **‘锁’**的方案。

悲观锁
  • 解释:这个锁是真实存在的,在mysql数据库当中,为指定的那个数据加锁,学过操作系统的话知道,相当于是一种临界资源。类似于互斥锁, 但是弊端就是处理不好很容易产生死锁!
    在这里插入图片描述
select stock from tb_sku where id=1 for update;

SKU.objects.select_for_update().get(id=1)
乐观锁
  • 解释: 乐观锁并不是真实存在的锁,而是在更新的时候判断此时的库存是否是之前查询出的库存,如果相同,表示没人修改,可以更新库存,否则表示别人抢过资源,不再执行库存更新
update tb_sku set stock=2 where id=1 and stock=7;

SKU.objects.filter(id=1, stock=7).update(stock=2)
mysql事务隔离级别的问题
  • 问题引入: 上面的乐观锁已经可以很好地处理我们的业务需要了,但是有一点,他是放在一个事务里面。 MySQL默认的 事务隔离级别是 可重复读,也就是说,不管其他用户如何购买商品,影响不到 我们这个事务中对数据的判断,因为事务读取数据不会 更新,加入别人事务完成买走了商品还有0件,我们乐观锁读取到的还是之前的1,不会去 刷新 读取到新数据。
  • 解决: 更改数据库的 事务级别。
mysql事务级别
Serializable:
  • 串行化,一个事务一个事务的执行
  • 执行效率太低了,意思就是只允许一个事务执行,执行完毕才允许其他事务执行。
Repeatable read(默认):
  • 可重复读,无论其他事务是否修改并提交了数据,在这个事务中看到的数据值始终不受其他事务影响
Read committed:
  • 读取已提交,其他事务提交了对数据的修改后,本事务就能读取到修改后的数据值
Read uncommitted:
  • 读取未提交,其他事务只要修改了数据,即使未提交,本事务也能看到修改后的数据值

使用乐观锁的时候,如果一个事务修改了库存并提交了事务,那其他的事务应该可以读取到修改后的数据值,所以不能使用可重复读的隔离级别,应该修改为读取已提交(Read committed)

修改事务级别方式(ubuntu):

在这里插入图片描述
在这里插入图片描述

现在是时候上我们的处理业务代码了

with transaction.atomic():   # 禁止事务自动提交
            # 开启事务
            sid = transaction.savepoint()
            # 2.创建订单基本对象
            order_id = '%s%09d' % (now.strftime('%Y%m%d%H%M%S'), user.id)
            total_count = 0
            total_amount = 0
            if pay_method == '1':
                # 待发货
                status = 1
            else:
                # 待支付
                status = 2
            order = OrderInfo.objects.create(
                order_id=order_id,
                user_id=user.id,
                address_id=address_id,
                total_count=0,
                total_amount=0,
                freight=10,
                pay_method=pay_method,
                status=status
            )

            # 3.查询商品对象
            skus = SKU.objects.filter(pk__in=cart_selected_int)

            # 4.遍历
            for sku in skus:
                cart_count = cart_dict_int.get(sku.id)
                # 4.1判断库存,不足则提示,如果足够则继续执行
                if sku.stock < cart_count:
                    # 回滚事务
                    transaction.savepoint_rollback(sid)
                    return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '商品[%d]库存不足' % sku.id})

                # 4.2修改sku的库存、销量
                # sku.stock -= cart_count
                # sku.sales += cart_count
                # sku.save()

                # 4.2 使用乐观锁
                stock_old = sku.stock
                stock_new = sku.stock - cart_count
                sales_new = sku.sales + cart_count
                result = SKU.objects.filter(pk=sku.id, stock=stock_old).update(stock=stock_new, sales=sales_new)
                # result表示sql语句修改数据的个数
                if result == 0:
                    # 库存发生变化,未成功购买
                    transaction.savepoint_rollback(sid)
                    return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '服务器忙,请稍候重试'})

                # 4.3创建订单商品对象
                order_sku = OrderGoods.objects.create(
                    order_id=order_id,
                    sku_id=sku.id,
                    count=cart_count,
                    price=sku.price
                )

                # 4.4 计算总金额、总数量
                total_count += cart_count
                total_amount += sku.price * cart_count

            # 5.修改订单对象的总金额、总数量
            order.total_count = total_count
            order.total_amount = total_amount + 10
            order.save()
            transaction.savepoint_commit(sid)
        # 6.删除购物车中选中的商品
        redis_cli.hdel('cart%d' % request.user.id, *cart_selected_int)
        redis_cli.srem('selected%d' % request.user.id, *cart_selected_int)

好的,基本上就处理完成了!

MySQL 事务实战:从库存扣减到隔离级别深度解析(含防超卖案例) 必用场景库存扣减、余额变更、订单创建等「关联操作」数据一致性要求高于性能的场景(如金融)慎用场景日志记录、报表统计等「非关键操作」读多写少的查询(可重复读会增加 MVCC 开销)最佳实践优先使用(兼顾一致性和性能)用UPDATE ... WHERE 条件替代先查后更新所有事务 SQL 必须走索引(避免锁表)通过合理设计事务和隔离级别,我们可以在高并发场景下守护数据一致性,让系统既健壮又高效。事务不是万能药,但没有事务万万不能——关键是在一致性、隔离性、性能之间找到平衡点。 阅读详情

相关推荐

【电商项目】---订单模块

订单模块开发:创建订单,取消订单

知识改变命运,ヾ(◍°∇°◍)ノ゙【求关注】 921

MySQL乐观锁电商库存并发问题应用

一、案例说明 银行两操作员(甲/乙)同时操作同一账户。两人同时读取一余额为 1000 元的账户,甲为该账户增加 100 元,乙同时为该账户扣除 50 元,甲先提交,乙后提交。最后实际账户余额为 1000-50=950,但本该为 1000+100-50=1050。这就是典型的并发问题。 乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” ..

firstcode666的博客 942

Python表白代码:“ 星光月夜烟花皆归你,我也归你”(满天烟花盛开、附番外玫瑰)

导语 "慢品人间烟火色 闲观人间岁月长" ———致自己​​​ ​ ???? 遇见我以后,我们的故事就开始了,愿你历经山河,仍觉得人间值得????。 ​ 星光月夜烟花皆归你,我也归你。关于烟花????大家都​知道多少?有多少表白故事情节都发生在烟 花下,想必木木子????不用说大家也知道叭~​​ 今天这则小短文就是关于烟花的故事!你准备好跟我一起进入烟花的世界了嘛? ​正文 “每一句文案,都有一个故事,你仔细听” ​ 1)环境安装???? 准备好:.

顾木子吖的博客 5万+

超卖问题之“悲观锁” or “乐观锁”

乐观锁是一种并发控制机制,它假设并发访问不会发生冲突,因此不会阻塞其他线程的访问。在乐观锁中,线程在访问共享资源之前不会获取锁,而是在更新共享资源时进行检查,如果发现其他线程已经更新了该资源,则会进行相应的处理(如重试或回滚)。乐观锁适用于对共享资源的冲突概率较低、读操作频率较高的场景,它具有较高的并发性能,但需要处理并发冲突的情况。

weixin_54931655的博客 547

Vue2项目实战:vue2-org-tree实现动态组织架构图

本文详细介绍了如何在Vue2项目中使用vue2-org-tree组件实现动态、可交互的组织架构图。内容涵盖从快速安装、基础渲染到核心功能实战,包括水平布局、节点展开折叠、响应式数据绑定、深度自定义节点内容以及事件处理。同时提供了性能优化、样式覆盖等避坑指南,并通过一个完整的企业级Demo展示了如何打造功能丰富的架构图,助力高效开发后台管理系统。

weixin_28040125的博客 522

【机器学习实战中阶】音乐流派分类-自动化分类不同音乐风格

数据下载地址:https://www.kaggle.com/datasets/andradaolteanu/gtzan-dataset-music-genre-classification/data背景音乐。专家们长期以来一直在尝试理解声音以及是什么使一首歌曲与另一首不同。如何可视化声音。是什么使一个音调与另一个不同。这个数据集希望能提供实现这些目标的机会。内容原始流派 - 包含10种流派,每种流派有100个音频文件,每个文件长度为30秒(著名的GTZAN数据集,声音的MNIST)

2143

MySQL事务隔离级别在电商系统中订单功能中的应用

事务的隔离级别是指多个事务并发的处理同一个数据的时候,一个事务修改了数据之后,其它事务何时可以看到修改后的结果。 主要分四种: 1、SERIALIZABLE:串行化,多个事务同时使用一个表的时候,不可以对这个表修改,否则会修改失败,如果想要修改这个表,只能一个事务一个事务顺序执行。 2、REPEATABLE-READ:可重复读,无论其它事务是否修改并提交了数据,在本事务中对数据的多次读取结果都相同,不受其他事务影响。 3、ERAD-COMMITTED:读取已提交,其它事务提交了对数据的修改之后,本事务就能读

73 665

【实战】S7-PLCSIM Advanced V3.0 授权问题排查指南(Error Code:-30与LicenseNotFound深度解析)

本文深度解析S7-PLCSIM Advanced V3.0启动时遇到的Error Code:-30与LicenseNotFound报错问题。文章提供了一套系统性的排查指南,从检查WinPcap驱动兼容性、确保Automation License Manager服务运行,到正确安装浮动授权以及清理系统残留缓存,逐步解决授权链条中的各个环节故障,帮助用户彻底解决仿真环境启动失败的问题。

weixin_29185167的博客 720

mysql乐观锁处理超卖_mysql处理高并发,防止库存超卖

一般电子商务网站都会遇到如团购、秒杀、特价之类的活动,而这样的活动有一个共同的特点就是访问量激增、上千甚至上万人抢购一个商品。然而,作为活动商品,库存肯定是很有限的,如何控制库存不让出现超买,以防止造成不必要的损失是众多电子商务网站程序员头疼的问题,这同时也是最基本的问题。从技术方面剖析,很多人肯定会想到事务,但是事务是控制库存超卖的必要条件,但不是充分必要条件。举例:总库存:4个商品请求人:a、...

weixin_28753691的博客 974

2026从0到1!C#工控机开发实战指南:新手一周就能跑通的完整项目

这篇文章摘要如下: 工业自动化领域工控机开发入门指南,针对零基础开发者提供从环境搭建到项目实战的全流程指导。文章首先解答工控机开发的3个核心问题,比较工控机与普通PC的区别,推荐使用C#作为开发语言。随后详细讲解开发环境配置、四大核心技术栈(通信协议、数据库、UI框架、多线程),并重点演示Modbus TCP通信的实现。最后通过一个完整的温度监控系统项目实战,展示如何用WPF构建实时数据采集界面,包括Modbus通信类编写、数据采集服务实现等关键代码片段。全文采用图解+代码的方式,帮助开发者快速掌握工控系统

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 701

硬件知识点-----SPI串联电阻、振铃、过冲

电阻取值,没有公式,一被传输线的特征阻抗为50欧姆左右,而TTL电路输出电阻大桃为13欧姆左右,在源端串一个33姆,大致和50相当,这样就可以柳制从终端反射回来的倍号,防止再次反射。传输时间tp=L/V,其中L是导线长度,V是电磁波在电路板中的传输速度V=C/sqrDk,其中Dk是光速衰减因子,对于电路板而言是铜线,Dk=4电磁波在电路板中的速度都是慢于光速的。实际上串联多大的电阻与传输线的阻抗有关,为了保证阻抗的连续性,如果传输线的特性阻抗 Z0与驱动源的输出阻抗 Zd不匹配,会引发信号的反射。

贾saisai的博客 2714

数据分析之MySql篇{电商数据处理案例}

电商数据处理案例 目标需求:将某电商脱敏后数据导入数据库进行加工处理,使用加工好的数据分析业务问题 数据获取   · 客户相关:UserInfo.csv:用户主表、RegionInfo.csv:区域表、UserAddress.csv:用户地址表   · 商品相关:GoodsInfo.csv:商品主表、GoodsBrand.csv:商品品牌表、GoodsColor.csv:商品颜色表、GoodsSize.csv:商品尺码   · 订单相关文件:OrderInfo.csv:订单主表、OrderDeta

樊鴻燁的博客 923

2025年11月架构设计师综合知识真题回顾,附参考答案、解析及所涉知识点(二)

本文整理了2025年11月架构设计师考试的16-30题真题及解析,涵盖多个计算机系统知识领域。主要内容包括:Linux绝对路径以根目录开始(A);模块调用下层数量用扇出表示(B);游乐园问题通过集合运算得出10人未游玩(B);磁盘位示图计算为200字节(C);测试用例核心是输入与预期输出(D)。其他题目涉及软件可靠性测试概念(B错)、评价程序准确度排序(真实程序最高,A)、测试阶段顺序(单元→组装→系统,A)、Web服务器压力测试前置步骤(C)、分时系统响应时间影响因素(用户数量多,A)、逆向工程方法(基于

一几文的编程学习笔记。 220

完整电商项目--(八)商品订单模块(1):订单结算与 mysql事务

文章目录订单结算页面重点:提交订单创建订单数据表注意事项:订单表介绍提交订单数据: 订单结算页面 位置:在购物车中选择好商品之后,就 可以点击 去结算按钮,进入到这个结算页面 这里最关键的一点是: 涉及到金钱的交易,要保证数据的准确性! 我们不能相信前端 传递过来的 商品价格信息,而是应该自己根据redis当中勾选的商品id,进行计算价格。 其他的并没有什么好说的,前端需要的数据从后端传递过去即可 (1)用户地址信息 (2)支付方式选择 支付方式,我们 直接选择是0,1就可以代表那种支

pythonstrat的博客 7122

【数据分析】R语言分段结构方程模型手把手教程(Piecewise Structural Equation Model)

分段结构方程模型(Piecewise Structural Equation Model, SEM)是一种用于分析变量之间因果关系的统计方法。它通过将复杂的因果关系分解为多个简单的线性模型来评估变量之间的直接和间接效应。与传统的结构方程模型(SEM)不同,分段结构方程模型不需要假设数据的多变量正态分布,因此在处理非正态数据时更为灵活。

专注生信领域 2646

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

使用乐观锁处理商品超卖的问题

1.问题引入 电商这类购物网站,涉及到多张数据表的IO操作,针对购物来说,用户将商品加入购物车时,会判断购买数量是否小于商品库存,这样才能成功加入购物车。同理,当用户提交订单时,通常的逻辑是:先判断购物车的每一个商品的购买数量是否小于库存量。如果小于库存量,表示可以提交订单,然后修改库存值,更新销量值。否则订单就会创建失败,返回库存不足的提示。但判断数量是否低于库存量,再到更新库存信息和销量信息时...

生有涯,知无涯 4394

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

MySQL 实战案例:电商系统数据库设计——订单事务与库存扣减的并发控制

在电商系统中,**订单创建与库存扣减**是最核心的业务之一,尤其是在高并发场景下(如秒杀、促销活动),如何**保证数据一致性、库存准确性**,成为数据库设计的关键挑战。本文将探讨 **MySQL 中订单事务与库存扣减的并发控制方案**,结合实际案例分析**事务隔离级别、乐观锁、悲观锁、分布式锁、消息队列**等技术,帮助你设计高效可靠的电商订单系统。

2272

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

mysql:MySQL事务隔离级别深度剖析

隔离级别选择指南业务场景推荐隔离级别补充措施财务交易结合悲观锁电商核心流程乐观锁+重试机制报表查询使用从库实时监控数据校正机制大厂检查清单- [ ] 所有事务显式指定隔离级别- [ ] 关键业务进行并发测试- [ ] 监控事务冲突指标- [ ] 定期评估隔离级别合理性性能调优参数# InnoDB优化参数终极建议默认使用REPEATABLE READ热点数据采用乐观锁分布式环境使用Seata建立隔离级别变更评审机制。

weixin_43290370的博客 986

电商系统MySQL事务实战:从订单创建到库存扣减

今天我就来分享一下在实战中如何使用MySQL事务来构建一个可靠的电商订单处理系统,重点解决高并发下的超卖、重复支付等问题。我自己使用后发现,在这个平台上测试事务处理特别方便,不需要繁琐的环境配置,就能快速验证各种并发场景下的数据一致性。订单创建是整个流程的起点,需要确保订单数据的完整性和一致性。在MySQL中,我们通常会创建一个订单表来存储订单的基本信息,比如订单号、用户ID、订单金额、下单时间等。乐观锁的实现关键在于在更新语句中加入版本号或库存数量的条件判断,确保只有在库存充足的情况下才能扣减成功。

EmeraldEagle36的博客 958

乐观锁解决并发下单问题和事务隔离级别的修改

一.乐观锁结果并发下单问题 1.查询商品 查询原有库存 查询原有销量 2.以商品和原有库存作为条件,用result接收结果,result=0,表示被修改,下单失败,若不等于零表示原始库存中途未被修改,则更新库存和销量 3.如果遇到网络信号不好,那么用户只买一个但是库存100时也会下单失败 购买成功包括两点: 库存大于购买商品数 库存没有被他人修改 4.所以使用无线循环,如果库存被改动,循环下单,直...

zw496862766的博客 413

Django电商项目(八)订单生成、悲观锁、乐观锁

Django电商项目订单生成mysql事务django使用事务提交订单页面创建订单后台view 订单生成 mysql事务 事务概念 一组mysql语句,要么执行,要么全不不执行。 事务的特点 1、原子性:一组事务,要么成功;要么撤回。 2、稳定性 :有非法数据(外键约束之类),事务撤回。 3、隔离性:事务独立运行。一个事务处理后的结果,影响了其他事务,那么其他事务会撤回。事务的100%隔离,需要牺牲速度。 4、可靠性:软、硬件崩溃后,InnoDB数据表驱动会利用日志文件重构修改。可靠性和高速度不可

行者 538

需求分析——基于Django框架的天天生鲜电商网站项目系列博客(一)

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 文章目录系列文章目录前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。 提示:以下是本篇文章正文内容,下面案例可供参考 一、pandas是什么? 示例:pandas 是基于Nu

IronmanJay 6414

muysq:MySQL事务隔离级别深度解析

业务特性:财务系统必须REPEATABLE READ性能要求:高并发场景可READ COMMITTED异常处理:必须有重试/补偿机制监控体系:实时跟踪事务指标最终建议采用"核心业务严格隔离+边缘业务灵活控制"的混合架构,这是经过阿里/字节海量业务验证的最佳实践。

weixin_43290370的博客 779

电商系统实战:MyBatis-Plus在订单模块的应用

订单模块最核心的就是要展示完整的订单信息,包括用户数据和商品数据。运营需要查看每日/每周订单数据,用MyBatis-Plus的QueryWrapper的between方法配合MySQL的DATE_FORMAT函数,可以轻松实现按天分组统计。后台管理系统必备的分页查询,用MyBatis-Plus的Page对象配合Wrapper条件构造器,三行代码就能实现。部署特别方便,他们的在线编辑器直接集成MyBatis-Plus环境,写完代码一键就能发布成可访问的API服务。记录下实战中的几个关键点,给需要的朋友参考。

CrystalwaveEagle34的博客 956

【数据库】MySQL事务隔离级别与并发问题深度解析

事务隔离级别的选择本质上是数据一致性与系统性能的权衡艺术。通过EXPLAIN分析查询执行计划使用检测锁状态进行压力测试模拟并发场景建立灰度环境验证隔离级别变更影响。

Luckstar2019的博客 984

mysql乐观锁处理超卖_使用乐观锁处理商品超卖的问题

1.问题引入电商这类购物网站,涉及到多张数据表的IO操作,针对购物来说,用户将商品加入购物车时,会判断购买数量是否小于商品库存,这样才能成功加入购物车。同理,当用户提交订单时,通常的逻辑是:先判断购物车的每一个商品的购买数量是否小于库存量。如果小于库存量,表示可以提交订单,然后修改库存值,更新销量值。否则订单就会创建失败,返回库存不足的提示。但判断数量是否低于库存量,再到更新库存信息和销量信息时,...

weixin_29111277的博客 413
上一篇: 完整电商项目--(八)商品订单模块(1):订单结算与 mysql事务
下一篇: 完整电商项目--(十)性能优化(1): 首页静态化
我是py呀
博客等级 码龄8年 205粉丝 130原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值