MySQL中乐观锁扣减库存原理是什么

1 基础知识

在电商系统中扣减库存是一步非常关键的操作,例如秒杀系统中一定要防止超卖情况出现,如果商家设置了100件库存但是最后卖出1000件,这样就会产生资金损失。在扣减库存时一般使用如下语句:

%ign%ignore_a_1%re_pre_1%

让我们分析这条语句如何有效防止库存超售,以便保护库存资源。在本文的演示中,我们采用MySQL Innodb引擎,隔离级别设为可重复读。

1.1 共享锁与排它锁

共享锁(share Lock)又被称为读锁,实现共享锁语句如下:

select lock in share mode

排它锁(exclusive Lock)又被称为写锁,实现排它锁语句如下:

select for updateupdatedeleteinsert

共享锁与排它锁兼容关系如下表:

MySQL中乐观锁扣减库存原理是什么

我们通过实例分析上述兼容关系,首先建一张测试表并写入测试数据:

CREATE TABLE `test_account` (  `id` bigint(20) NOT NULL,  `name` varchar(20) DEFAULT NULL,  `account` bigint(20) DEFAULT NULL,  `version` bigint(20) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;insert  into `test_account`(`id`,`name`,`account`,`version`) values (1,'A',100,1);insert  into `test_account`(`id`,`name`,`account`,`version`) values (2,'B',200,1);insert  into `test_account`(`id`,`name`,`account`,`version`) values (3,'C',300,1);

(1) 读读兼容

共享锁与共享锁之间兼容,在如下实例中session1在t3时刻,session2在t4时刻执行查询均可以获取预期结果:

MySQL中乐观锁扣减库存原理是什么

(2) 读写互斥

共享锁与排它锁之间互斥,在如下实例中session1在t3时刻加共享锁,可以正确读取结果,但是session2在t4时刻尝试加排它锁,但是此时锁被session1占有,session2需要等待,当session1长时间不释放锁时,session2抛出锁超时异常:

MySQL中乐观锁扣减库存原理是什么

(3) 写写互斥

排它锁与排它锁之间互斥,在如下实例中session1在t3时刻加排它锁,可以正确读取结果,但是session2在t4时刻尝试加排它锁,但是此时锁被session1占有,session2需要等待,当session1长时间不释放锁时,session2抛出锁超时异常:

MySQL中乐观锁扣减库存原理是什么

1.2 当前读与快照读

MySQL Innodb存储引擎实现基于多版本并发控制协议MVCC,在MVCC并发控制中读操作可以分成快照读与当前读。

快照读不需要加锁,读取的是记录可见版本,有可能是历史版本。类比于订单快照,即使用户下单后商品价格发生变化,订单快照仍然保持不变。实现当前读语句如下:

select

为了读取最新版本的记录时不被其它事务修改,需要对当前记录进行加锁。实现当前读语句如下:

select lock in share modeselect for updateupdatedeleteinsert

我们通过一个实例分析快照读和当前读,session2在t4时刻修改记录并在t5时刻提交,session1在t6时刻进行了快照读,读取的是本事务开始时结果100,在t7时刻进行了当前读,读取的是记录最新版本结果101:

MySQL中乐观锁扣减库存原理是什么

当前读流程是怎么样的呢?我们以update为例进行分析当前读流程:

MySQL中乐观锁扣减库存原理是什么

第一次程序实例发出当前读请求,存储引擎返回满足where条件的第一条记录并加锁,程序实例再发出更新请求,存储引起操作完成响应成功。依次执行直到所有满足where条件记录执行完成为止。

这里我们做一些引申,RR级别提供了两种机制避免幻读问题:第一种方式是快照读,读取的是当前事务开启时的快照。一种针对当前读的方法是使用Next-Key Lock机制来防止幻读。

2 乐观锁原理

我们通过一个问题将上述知识整合起来:有两个线程在同一时刻执行如下语句,请问id=1这条记录account值会不会成功扣减两次?

update test_account set account = account - 100, version = version + 1 where id = 1 and version = 1

上述语句使用了乐观锁,我们知道乐观锁就是对资源进行保护的,所以答案是不会扣减两次,但是不能就此止步,需要结合第一章节知识进行进一步分析:

MySQL中乐观锁扣减库存原理是什么

t2时刻session1和session2同时执行update操作,由于update会加排它锁,所以两者只能有一个成功:session1成功,session2阻塞等待排它锁释放。

t3时刻session1提交事务释放排它锁,此时session2获取到锁进行当前读,但是此时id=1记录version值已经变成了2,执行语句已经查询不到待更新数据,所以没有记录发生更新。

3 扣减库存原理

如果理解了第二章节乐观锁原理,那么扣减库存原理已经显而易见,我们假设商品只剩下1件库存,如果两个线程同时执行扣减库存,会发生超卖的情况吗?

MySQL中乐观锁扣减库存原理是什么

t2时刻session1和session2同时执行updatek扣减库存,由于update会加排它锁,所以两者只能有一个成功:session1成功,session2阻塞等待排它锁释放。

t3时刻session1提交事务释放排它锁,此时session2获取到锁进行当前读,但是此时商品1库存已经变为0,已经不满足(where stock – 1 >= 0)条件,执行语句已经查询不到待更新数据,所以没有记录发生更新。

以上就是MySQL中乐观锁扣减库存原理是什么的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/145386.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月2日 05:29:52
下一篇 2025年12月2日 05:31:26

相关推荐

  • Linux journalctl与systemctl status结合分析

    先看 systemctl status 确认服务状态,再用 journalctl 查看详细日志。例如 nginx 启动失败时,systemctl status 显示 Active: failed,journalctl -u nginx 发现端口 80 被占用,结合两者可快速定位问题根源。 在 Lin…

    2025年12月6日 运维
    100
  • Pboot插件数据库连接的配置教程_Pboot插件数据库备份的自动化脚本

    首先配置PbootCMS数据库连接参数,确保插件正常访问;接着创建auto_backup.php脚本实现备份功能;然后通过Windows任务计划程序或Linux Cron定时执行该脚本,完成自动化备份流程。 如果您正在开发或维护一个基于PbootCMS的网站,并希望实现插件对数据库的连接配置以及自动…

    2025年12月6日 软件教程
    000
  • 「世纪传奇刀片新篇」飞利浦影音双11声宴开启

    百年声学基因碰撞前沿科技,一场有关声音美学与设计美学的影音狂欢已悄然引爆2025“双十一”! 当绝大多数影音数码品牌还在价格战中挣扎时,飞利浦影音已然开启了一场跨越百年的“声”活革命。作为拥有深厚技术底蕴的音频巨头,飞利浦影音及配件此次“双十一”精准聚焦“传承经典”与“设计美学”两大核心,为热爱生活…

    2025年12月6日 行业动态
    000
  • 环境搭建docker环境下如何快速部署mysql集群

    使用Docker Compose部署MySQL主从集群,通过配置文件设置server-id和binlog,编写docker-compose.yml定义主从服务并组网,启动后创建复制用户并配置主从连接,最后验证数据同步是否正常。 在Docker环境下快速部署MySQL集群,关键在于合理使用Docker…

    2025年12月6日 数据库
    000
  • 微信如何开启翻译功能_微信翻译功能的语言切换

    首先开启微信翻译功能,长按外文消息选择翻译并设置“始终翻译此人消息”;接着在“我-设置-通用-多语言”中切换目标语言以优化翻译方向;若效果不佳,可复制内容至第三方工具如Google翻译进行高精度处理。 如果您在使用微信与不同语言的联系人沟通时,发现聊天内容无法理解,则可能是未开启微信内置的翻译功能或…

    2025年12月6日 软件教程
    000
  • 如何在mysql中分析索引未命中问题

    答案是通过EXPLAIN分析执行计划,检查索引使用情况,优化WHERE条件写法,避免索引失效,结合慢查询日志定位问题SQL,并根据查询模式合理设计索引。 当 MySQL 查询性能下降,很可能是索引未命中导致的。要分析这类问题,核心是理解查询执行计划、检查索引设计是否合理,并结合实际数据访问模式进行优…

    2025年12月6日 数据库
    000
  • 如何在mysql中安装mysql插件扩展

    安装MySQL插件需先确认插件文件位于plugin_dir目录,使用INSTALL PLUGIN命令加载,如INSTALL PLUGIN keyring_file SONAME ‘keyring_file.so’,并确保用户有SUPER权限,最后通过SHOW PLUGINS验…

    2025年12月6日 数据库
    000
  • php查询代码怎么写_php数据库查询语句编写技巧与实例

    在PHP中进行数据库查询,最常用的方式是使用MySQLi或PDO扩展连接MySQL数据库。下面介绍基本的查询代码写法、编写技巧以及实用示例,帮助你高效安全地操作数据库。 1. 使用MySQLi进行查询(面向对象方式) 这是较为推荐的方式,适合大多数中小型项目。 // 创建连接$host = ‘loc…

    2025年12月6日 后端开发
    000
  • 如何在mysql中定期清理过期备份文件

    通过Shell脚本结合cron定时任务实现MySQL过期备份文件自动清理,首先统一备份命名格式(如backup_20250405.sql)并存放在指定目录(/data/backup/mysql),然后编写脚本使用find命令删除7天前的.sql文件,配置每日凌晨2点执行的cron任务,并加入日志记录…

    2025年12月6日 数据库
    000
  • VSCode的悬浮提示信息可以自定义吗?

    可以通过JSDoc、docstring和扩展插件自定义VSCode悬浮提示内容,如1. 添加JSDoc或Python docstring增强信息;2. 调整hover延迟与粘性等显示行为;3. 使用支持自定义提示的扩展或开发hover provider实现深度定制,但无法直接修改HTML结构或手动编…

    2025年12月6日 开发工具
    000
  • php数据库如何实现数据缓存 php数据库减少查询压力的方案

    答案:PHP结合Redis等内存缓存系统可显著提升Web应用性能。通过将用户信息、热门数据等写入内存缓存并设置TTL,先查缓存未命中再查数据库,减少数据库压力;配合OPcache提升脚本执行效率,文件缓存适用于小型项目,数据库缓冲池优化和读写分离进一步提升性能,推荐Redis为主并防范缓存穿透与雪崩…

    2025年12月6日 后端开发
    000
  • 如何在mysql中使用角色组合优化权限管理

    答案:MySQL角色通过封装权限实现集中管理。创建如app_reader等角色并授予权限,再分配给用户alice并设默认角色,支持组合使用,定期审计并通过系统视图查看,提升安全与运维效率。 在MySQL中,角色(Role)是一种强大的权限管理工具,能够简化用户权限的分配与维护。通过创建角色并将其赋予…

    2025年12月6日 数据库
    000
  • 如何在mysql中使用索引提高查询效率

    合理创建索引可显著提升MySQL查询效率,应优先为WHERE、JOIN、ORDER BY等高频字段建立B-Tree复合索引,如CREATE INDEX idx_status_created ON users(status, created_at, id),并遵循最左前缀原则;避免在索引列使用函数或前…

    2025年12月6日 数据库
    000
  • VSCode插件:GitLens使用详解

    GitLens是VSCode中强大的Git增强插件,提供行级代码追踪、提交历史浏览、版本对比、跨文件导航及与GitHub等平台集成;通过启用Current Line Blame和In-Line Blame,可实时查看每行代码的作者与修改时间;支持按分支、作者过滤提交记录,比较差异,并利用Go Bac…

    2025年12月6日 开发工具
    000
  • PHP中向数组对象添加或修改属性的实用指南

    本教程详细介绍了如何在php中高效地向数组中的对象添加或修改属性,尤其是在处理json数据时。文章强调了利用php内置的`json_decode()`和`json_encode()`函数进行数据转换和操作的重要性,避免手动构建json字符串,从而确保数据结构的完整性和代码的健壮性。 在PHP开发中,…

    2025年12月6日
    000
  • mysql如何备份存储过程和函数

    最直接且推荐的方式是使用mysqldump工具并添加–routines参数,可完整导出存储过程和函数;若需跨版本迁移,应结合–triggers、处理DEFINER用户、验证SQL_MODE,并在测试环境充分验证恢复与兼容性。 MySQL备份存储过程和函数,最直接且推荐的方式是…

    2025年12月6日 数据库
    000
  • 外媒:V社亲手摧毁CS2饰品市场 或许永难复原!

    《反恐精英2》的皮肤经济正遭遇前所未有的崩塌。在10月23日valve发布更新后的48小时内,这项允许玩家使用“交易升级合约”将五件隐秘级别皮肤兑换为刀具或手套的功能上线后,整个市场估值从约60亿美元骤降至30亿美元。短短两天内,数十亿虚拟资产化为乌有,令无数玩家对这个曾是全球最大数字游戏经济体之一…

    2025年12月6日 游戏教程
    000
  • edge浏览器提示“您的时钟快了”或“时钟落后”如何校准_Edge浏览器时钟不同步校准方法

    首先启用自动时间同步,若无效则手动调整日期和时间;仍无法解决时更换Internet时间服务器,并通过命令提示符强制重启时间服务完成同步。 如果您在使用Edge浏览器访问某些网站时,收到“您的时钟快了”或“时钟落后”的安全警告,这通常是因为系统时间与网络服务器时间不同步,导致SSL证书验证失败。此问题…

    2025年12月6日 电脑教程
    000
  • MySQL模糊查询:高效处理含空格和多格式电话号码

    在mysql数据库中,当电话号码字段包含多种格式和空格时,传统的`like`查询可能无法返回预期结果。本文将介绍如何利用`replace`函数在查询时动态移除电话号码中的空格,从而实现准确的模糊匹配。同时,我们还将探讨性能考量及数据标准化等最佳实践,帮助您优化数据库查询和数据质量。 挑战:含空格电话…

    2025年12月6日 后端开发
    000
  • JavaScript语音识别与合成

    答案:JavaScript通过Web Speech API实现语音识别与合成。使用SpeechRecognition将语音转文本,需在安全上下文并获麦克风权限;利用SpeechSynthesis将文本转语音,可设置语速、音调等参数。两者结合可用于语音助手、无障碍阅读等场景,但语音识别兼容性有限,主要…

    2025年12月6日 web前端
    000

发表回复

登录后才能评论
关注微信