[英]Handling concurrency in Laravel
我正在创建一个与 MySQL 库存数据库交互的 API。 我们有 15 个用户可以预订产品,按以下方式更新数据库:
on-hand
价值并增加产品的reserved
价值。 inventory
表如下所示:
id int
sku varchar
on-hand int
reserved int
问题是:如果 2 个用户同时尝试更新该行,如何处理该行的更新?
我考虑的第一个方法是使用Transactions :
<?php
function reserveStock()
{
$db->beginTransaction();
// SELECT on-hand, reserved from inventory
// Update inventory values
$db->commit();
return response()->json([ 'success' => 1, 'data' => $data ])
}
第二个是使用悲观锁定:
<?php
function reserveStock()
{
// SELECT on-hand, reserved from inventory with ->sharedLock()
// Update inventory values
return response()->json([ 'success' => 1, 'data' => $data ])
}
第三个是创建一个值为 cero 的updating
字段。 选择要更新的产品时,我会在对该行执行任何操作之前检查updating
字段。 我在这里看到的问题是我必须循环updating != 0
直到它们可用。 更多选择和更新来自他的方法。
哪种行动方式最好? 可能有比我在这里写的更多的选择。
既不要使用事务,也不要使用悲观主义者锁定。
也不要使用更新。
对于赛车状况,您最好查看数据库,并摆脱更新,而使用插入。 制作数据透视表以适应用户和产品之间的连接。 并且仅使第一个连接记录(其中id较小)成为实际记录。
如果需要更多说明,请参考以下示例 :
假设有2位用户竞相购买该产品。 他们俩几乎同时在数据透视表中创建记录,但应该有人来做,对吧? 他们俩都进行非常小的事务来持久化数据。 然后-他们俩都读取数据透视表以验证谁成功。 这两个记录的第一条记录都是相同的,不会有任何阻塞使用(显式租用)。 因此,一个客户将获得他的记录并感到高兴,而另一个将要重新申请以获得另一种产品。
问题解决了。
我知道我迟到了,但我可以帮助像我这样遇到类似问题的人。 您可以通过使用作业/队列来解决这个问题。 这样,与用户相关的任何“交易”都不会与另一个用户“同时”运行。 考虑查看这篇关于并发攻击的文章,我相信你会喜欢的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.