4

我有一个场景,我从客户那里收到了出租车请求,然后我向多个司机发送了取货请求。现在想象一下,如果两个收到请求的司机同时点击“接受”按钮,那么哪个司机会搭车。

我有一个包含ride_id、driver_id、已完成(布尔)列的乘车表。

到目前为止,我正在做的是在点击“接受”按钮后立即调用 API。此 GET 请求 API 检查行程是否已完成。如果是,我会向司机显示一​​条消息,说乘车已经完成,否则我会点击另一个 POST API 请求,它将 DB 中的已完成值更新为 true,并更新 driver_id。

现在进入我们的场景,当两个驱动程序同时点击“接受”时,将发出两个 GET 请求,并且两者都将得到“未完成”作为响应,此后两者都将发送一个 POST 请求。现在我很困惑谁的数据将在数据库中更新。

我在后端使用 PHP 和 MYSQL 作为数据库。

4

2 回答 2

4

您正在通过运行 a 来创建竞争条件SELECT,然后运行UPDATE​​. 但是所有数据库都可以非常有效地做的一件事是管理并发性。因此,更简单的解决方案是在驱动程序点击接受按钮时直接运行更新,例如:

UPDATE ride 
SET driver_id = :driver_id, fulfilled = 1 
WHERE ride_id = :ride_id AND fulfilled = 0

然后在您的应用程序中检查记录是否受到查询的影响。如果是,那么这个司机就赢了。如果没有记录受到影响,则意味着之前有其他司机接管了该行程。

于 2019-10-12T17:32:20.887 回答
2

两个驱动程序同时按下接受按钮不会转化为同时更新单行。你这种情况发生的可能性非常小。

但如果确实发生了,则不一定是两个事务更新一行的情况。这是一个事务尝试更新当前正在更新的行的情况。在任何情况下,当前更新该行的事务都会获得对该行的锁定,并且尝试更新同一行的任何其他事务都将排队。

第一个事务完成更新后,它释放锁,队列中其他事务中的第一个获得锁以执行它自己的更新。这一直持续到等待队列为空。

有趣的是,这个工具已经内置在大多数关系数据库中,因此您不必担心两个事务会同时更新数据库。然而,一个有趣的研究领域是如何在这种场景中管理事务队列(例如,优先考虑等待事务)。

于 2019-10-12T17:39:14.857 回答