gpt4 book ai didi

mysql - 使用mysql更新账户余额

转载 作者:行者123 更新时间:2023-11-30 23:34:24 31 4
gpt4 key购买 nike

我在用户表上有一个字段,用于保存用户的帐户余额。用户可以使用我的服务执行很多操作,这将导致他们的余额发生快速变化。

我正在尝试使用 mysql 的可序列化隔离级别来确保多个用户操作不会错误地更新值。 (操作 A 和操作 B 同时要从余额中扣除 1 美元。)但是,我遇到了很多死锁错误。

我如何正确地做到这一点,而不会遇到所有这些死锁,并且仍然保持余额字段是最新的?

简单模式:用户有一个 ID 和一个余额。

我在使用教义,所以我正在做类似以下的事情:

$con->beginTransaction();
$tx = $con->transaction;
$tx->setIsolation('SERIALIZABLE');

$user = UserTable::getInstance()->find($userId);
$user->setBalance($user->getBalance() + $change);
$user->save();
$con->commit();

最佳答案

首先尝试在事务上使用可序列化隔离级别是个好主意。这意味着您至少知道什么是事务,而隔离级别是最大的问题之一。

请注意,serializable 并不是真正的可串行性。关于 this previous answer 的更多信息,当你有时间阅读时:-)。

但最重要的部分是您应该考虑到由于串行性失败而自动回滚您的事务是一个正常的事实,正确的做法是构建您的应用程序,以便事务可能会失败并且应该被重放。

一个简单的解决方案,对于会计方面的事情,我喜欢这个简单的解决方案,因为我们可以预测所有事实,没有意外,所以,一个解决方案是执行表锁。这不是一个很好和优雅的解决方案,没有行级锁,只是简单的大表锁(并且总是以相同的顺序)。之后,您可以单人操作,然后释放锁。表的行上没有多用户并发,没有下一行魔法锁失败(参见前面的链接)。这肯定会减慢您的写操作,但如果每个人都以相同的顺序执行表锁,您只会遇到锁超时问题,没有死锁,也没有“不可序列化的自动回滚”。

编辑

根据您的代码示例,我不确定您是否可以在开始时之后设置事务隔离级别。您应该激活 MySQL 上的查询日志并查看发生了什么,然后检查 CMS 运行的其他事务是否仍处于可序列化级别。

关于mysql - 使用mysql更新账户余额,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8828245/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com