乐观锁加事务扣余额,如何保证只扣一次且一次成功?

乐观锁加事务扣余额,如何保证只扣一次且一次成功?

乐观锁加事务扣余额一次成功仅扣一次的原因和解决办法

在使用乐观锁和事务进行用户余额扣除时,如果只扣除一次金额,可能是以下原因造成的:

1. 事务范围不正确

你的代码将余额扣除逻辑放在了事务之外,导致扣余额操作无法受到事务隔离。

2. 乐观锁使用错误

乐观锁的目的是防止数据并发修改,你的代码使用 find 查询用户信息,实际上并没有真正实现乐观锁的机制。

解决方案:

将余额扣除逻辑放入事务中,这样所有涉及平衡的操作都将被隔离。正确使用乐观锁,在扣除余额前,使用 where([‘id’ => $user[‘id’], ‘balance’ => $oldmoney]) 查询用户是否存在,如果不存在则提示错误,否则进行扣除余额操作。

错误代码:

$user = $this->getuser(); //从数据库获取购买商品的用户信息$oldmoney = $user['balance']; //得到用户旧余额$orderoffer = $this->getordermoney($orderid); //获取次订单价格if($oldmoney error('账户余额不足');//乐观锁方案$newmoney = $oldmoney - $orderoffer['price']; //计算出新余额$newuser = smsuser::where(['id' => $user['id'],'balance' => $oldmoney])->find();if(!$newuser) $this->error('用户不存在');//开启数据库事务db::transaction(function () use($newuser,$orderid,$newmoney){    $newuser->balance = $newmoney;    $result = $newuser->save();    if(!$result) $this->error('保存余额失败');     //创建订单 code     //扣除库存 code     //创建用户余额变动记录 code        db::commit(); //提交事务         })

正确代码:

$user = $this->getUser(); //从数据库获取购买商品的用户信息$oldMoney = $user['balance']; //得到用户旧余额$orderOffer = $this->getOrderMoney($orderId); //获取次订单价格if($oldMoney error('账户余额不足');//乐观锁方案$newMoney = $oldMoney - $orderOffer['price']; //计算出新余额//开启数据库事务DB::transaction(function() use($user, $newMoney) {    $result = SmsUser::where(['id' => $user['id'], 'balance' => $oldMoney])        ->update(['balance' => $newMoney]);    if (!$result) throw new Exception('保存余额失败');        //创建订单 code    //扣除库存 code    //创建用户余额变动记录 code        DB::commit(); //提交事务});

以上就是乐观锁加事务扣余额,如何保证只扣一次且一次成功?的详细内容,更多请关注创想鸟其它相关文章!

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

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月10日 23:48:41
下一篇 2025年12月10日 23:48:50

相关推荐

  • PHP中json_encode和serialize的区别

    json_encode用于将php数据结构转换为json格式,适用于跨平台数据交换;serialize则用于php内部的数据持久化或会话管理。1.serialize是php特有的,生成的字符串含php类型信息,与其他语言不兼容;2.json是通用格式,几乎所有语言都支持,确保互操作性;3.seria…

    2025年12月11日 好文分享
    000
  • PHP怎样解析EPUB电子书 PHP解析EPUB格式的完整教程

    用php解析epub电子书的方法如下:1. 解压epub文件,使用php的ziparchive类解压并提取内容;2. 解析content.opf文件,通过simplexml_load_file函数读取xml结构,获取书名、作者等元数据;3. 读取内容文件,遍历manifest节点中的html文件路径…

    2025年12月11日 好文分享
    000
  • PHP中continue语句有什么用?

    在php中,continue语句用于跳过循环的当前迭代,直接进入下一次迭代。1) 在处理大数据集时,continue可跳过不符合条件的元素,提高代码可读性。2) 使用时需注意避免逻辑错误,确保清楚哪些代码会被跳过。3) 在嵌套循环中,continue 2可跳过外层循环的当前迭代,增强代码控制。 在P…

    2025年12月11日
    000
  • 如何检查PHP数组是否为空?

    在php中检查数组是否为空,应使用count()函数。1) count($array) === 0能准确判断数组是否为空,不受元素值影响。2) empty()函数检查变量是否为假值,可能误判数组为空。 检查PHP数组是否为空看似简单,但实际上涉及到一些有趣的细节和常见的陷阱。让我们深入探讨一下如何高…

    2025年12月11日
    000
  • ​PHP8.1启用JIT编译器:配置参数与性能提升实测

    在php8.1中,可以通过在php.ini文件中设置opcache.jit=1205和opcache.jit_buffer_size=64m来启用jit编译器。1)在php.ini文件中添加配置opcache.jit=1205和opcache.jit_buffer_size=64m。2)根据应用需求…

    2025年12月11日
    100
  • 如何按值对PHP数组进行降序排序?

    在php中,使用arsort()函数可以对数组按值进行降序排序。1) 使用arsort()函数对数组进行排序,2) 注意数据类型转换可能导致意外的排序结果,3) 考虑性能问题,arsort()基于快速排序,时间复杂度为o(n log n),4) 如果需要保留原数组不变,使用asort()函数并克隆数…

    2025年12月11日
    000
  • 在Laravel框架中如何解决“Too many open files”错误?

    在laravel框架中解决“too many open files”错误的方法 在使用php7.3和laravel框架执行定时任务时,你可能会遇到一个错误提示,指出“打开文件太多”,错误信息大致如下: [2023-03-15 00:14:13] local.ERROR: include(/www/v…

    好文分享 2025年12月11日
    100
  • php中的卷曲:如何在REST API中使用PHP卷曲扩展

    php客户端url(curl)扩展是开发人员的强大工具,可以与远程服务器和rest api无缝交互。通过利用libcurl(备受尊敬的多协议文件传输库),php curl有助于有效执行各种网络协议,包括http,https和ftp。该扩展名提供了对http请求的颗粒状控制,支持多个并发操作,并提供内…

    2025年12月11日
    000
  • Git服务器重装后,git pull一直提示输入密码怎么办?

    Git服务器重装后,持续提示输入密码的解决方案 重装Git服务器后,git pull 命令反复要求输入密码?本文提供详细的解决方法,助您快速恢复正常代码拉取流程。 问题背景: 您搭建的Git服务器并非基于GitHub或HTTPS协议,重装系统后,即使目录结构保留,git pull 仍然需要密码验证。…

    2025年12月11日
    100
  • 高并发秒杀下,如何保证Redis和数据库库存一致性?

    高并发秒杀:PHP+Redis与数据库库存一致性解决方案 高并发秒杀系统中,如何确保Redis缓存库存与数据库库存数据一致性是核心挑战。本文分析基于Redis原子自减操作和数据库操作的秒杀流程,探讨可能出现的问题及解决方案。 常见的秒杀流程:下单 -> Redis扣减库存 -> 创建订单…

    2025年12月11日
    000
  • Composer自定义包安装路径调试:如何打印$installPath变量?

    深入Composer自定义包调试:轻松打印安装路径 在使用Composer管理依赖时,自定义包的安装路径并非总是默认的vendor目录。这通常需要编写Composer插件来实现。然而,调试自定义包的安装过程,例如打印安装路径$installPath,却可能比较棘手。本文将提供一种简单方法,无需复杂配…

    2025年12月11日
    000
  • PHP闭包函数:显式参数传递和隐式变量捕获有何区别?

    PHP闭包函数参数传递机制深度解析 PHP闭包函数(匿名函数)能够访问其定义作用域中的变量,但其参数传递方式存在细微差别,主要分为显式参数传递和隐式变量捕获两种。本文将详细对比这两种方式。 示例代码展示了两种闭包函数的定义: function (int $timer_id) use ($sms, $…

    2025年12月11日
    000
  • 如何用PHP和CURL高效采集新闻列表及详情?

    本文将阐述如何利用PHP和cURL高效抓取目标网站的新闻列表和新闻详情,并展示最终结果。 关键在于高效运用cURL获取数据,处理相对路径并提取所需信息。 首先,解决第一个挑战:从列表页(例如,页面1)提取新闻标题和完整URL。 代码示例如下: <?php$url = 'http://…

    2025年12月11日
    100
  • PHP foreach循环中&&运算符的妙用:如何利用短路求值避免JSON解码错误?

    PHP foreach 循环与 && 运算符:巧妙利用短路求值避免 JSON 解码错误 在 PHP 中,foreach 循环常用于遍历数组。本文将探讨在 foreach 循环中使用 && 运算符的技巧,特别是如何利用短路求值特性来避免 JSON 解码错误。 以下代码片…

    2025年12月11日
    000
  • HTML表单onsubmit事件失效,如何排查表单验证问题?

    HTML表单提交验证失效:排查与解决 在使用HTML表单进行数据提交时,onsubmit事件常用于客户端验证,确保数据符合要求后再提交至服务器。然而,onsubmit事件有时失效,导致表单直接提交,本文将分析一个案例,解决onsubmit=”return check()”失效的问题。 问题描述: 用…

    2025年12月11日
    000
  • PHP GlobIterator如何实现自然排序而不是字符串排序?

    PHP文件遍历与自然排序:巧妙解决GlobIterator排序难题 在PHP中,使用GlobIterator遍历文件时,常常遇到排序问题。理想情况下,我们希望按照自然数字顺序(1, 2, 3…10, 11…)读取文件,以便后续操作。然而,GlobIterator默认使用字符串…

    2025年12月11日
    000
  • 苹果M1芯片Mac上编译安装Redis失败怎么办?

    苹果m1芯片mac编译安装redis失败的排查与解决 在苹果M1芯片的Mac电脑上编译安装Redis,常常会遇到各种问题,例如编译失败等。本文将指导您如何有效地排查和解决这些问题。 很多用户反馈编译错误,但仅提供截图不足以诊断问题。 为了高效解决,务必提供完整的错误日志文本。 以下几个关键点需要关注…

    2025年12月11日
    000
  • PHP一维数组如何高效转换为指定的多维树状结构?

    PHP数组结构转换:一维数组到多维树状结构的优雅实现 本文介绍如何将PHP一维数组高效地转换为指定的多维树状结构。假设我们有一个包含项目名称、型号和位置信息的数组,目标是将其转换为树形结构:项目名称作为一级节点,型号作为二级节点,位置作为三级节点。 初始一维数组: $arr = [ [‘name’ …

    2025年12月11日
    000
  • PHP PDO连接远程MySQL数据库:php.ini配置需要修改吗?

    PHP PDO连接远程MySQL数据库:关于php.ini配置的常见误区 许多PHP开发者在使用PDO连接远程MySQL数据库时,常常误认为需要修改php.ini文件。本文将对此进行详细解释,并消除一些常见的误解。 在Linux环境下,开发者可能会发现php.ini中关于PDO的配置项很少,主要涉及…

    2025年12月11日
    000
  • PHP乐观锁与事务结合扣除余额:如何避免并发更新导致余额只扣除一次?

    PHP乐观锁与数据库事务结合扣除余额:深度解析并发更新问题 在PHP开发中,使用乐观锁和数据库事务处理余额扣除操作时,常常面临并发更新的挑战。本文将通过一个案例分析,深入探讨如何避免并发更新导致余额只扣除一次的问题,并提供有效的解决方案。 案例:假设用户同时购买5个单价1元的商品,初始余额为100元…

    2025年12月11日
    000

发表回复

登录后才能评论
关注微信