mysql - 并发更新
问题描述
我正在构建一个处理Wallet的应用程序。我有这个钱包的提现和提现。
当此钱包的 + 或 - 发生更新时,我遇到了问题。
看场景:
用户提现,系统检索此钱包的余额,如下所示:
select * from Wallet where idUser = x;
所以上面的这个查询返回了钱包,并且 * 得到了“余额”列并像这样
wallet.balance += amount;
在此之后,我将进行更新以插入此钱包的新“余额”并执行此操作
update Wallet set balance = balanceVar where idWallet = x;
直到这里一切看起来都很好,但是当我们同时处理现金进出时,这种情况下更好的情况是什么。
把这个放在队列中?
更新时锁定表?
这是我第一次处理这样的系统,我真的很困惑该怎么做。
解决方案
您的SELECT
thenUPDATE
方案直接导致竞争条件,其中两个进程可以选择相同的数据,然后执行相同的更新,从而导致发生两个更新但只记录一个更新的不一致。
避免这种情况的方法是使用原子操作(即不能分割的操作)。
在您的情况下,您应该直接更新钱包:
update Wallet set balance = balance+10 where idWallet = 'x';
在另一个进程可以执行另一个更新之前,此更新将完全完成。
你可以用这个想法走得更远。对于提款,只有当余额大于或等于提款时,您才能更新钱包:
update Wallet set balance = balance-10 where idWallet = 'x' and balance >= 10;
您可以测试ROW_COUNT()
一下操作是否成功。PHP 提供mysqli_affected_rows()
或PDOStatement::rowCount()
用于此目的。
推荐阅读
- robotics - 位置控制器能够平移关节,但不能旋转
- django - 如何使用 Django 中的 OneToOne 字段创建多种类型的用户?
- api - Swagger - 从定义中检索“示例值”以构建测试
- safari - CAS v6.4:注册服务时不重定向 safari (macOS Catalina) 中的登录页面
- python - 如何在没有 Process 类的情况下从 C# 执行 Python 脚本
- flutter - 如何使状态栏颜色与颤动中的容器颜色相同
- ios - 无法连接到 iPhone se2 上的 React-Native 语音通话
- tensorflow - 框架暗网有多少模型?
- python - 机器翻译变压器输出 - “未知”令牌?
- go - 结构体和 GoRoutines,切换实例?