带有行条目的php竞争条件数据库

时间:2018-03-26 09:36:17

标签: php mysql race-condition

所以我试图找出如何避免竞争条件。 我有一个产品,您可以预订有限的资源。

每个资源都有多个容量。容量是使用名为booking_resources的数据库表中的行数计算的,其中每个预订的资源都有一行。

在代码执行期间,我会执行多项检查,例如:

  • 此人是否有权访问
  • 资源是否在给定时间范围内可用
  • 预订选项是否有效
  • 预订

当"进行预订"预订所需的资源将插入到booking_resources表中。这使得具有resource_id的行数增加,这反过来将使得下一次检查是在给定时间帧中可用的资源。 我的问题是我找不到任何关于在这种情况下做什么的文档。 我应该在资源表中添加一个额外的列,并以这种方式锁定行? (我使用 innodb

我已经阅读了有关使用select ...进行更新的内容..但这在我的情况下没有意义,因为我不会"缓存"行中的预订数量。 整个想法是我有一个全天候可用的资源,每个预订都需要一些容量。它可能具有10的容量(这意味着我可以有10个人同时使用该资源)。这也意味着(理论上)人们的资源预订可以重叠,只要不超过10人同时使用它。

希望我的问题可以让我了解我面临的问题,并希望你们有一个优雅的解决方案,以防止我的应用程序超量预订。

数据结构:

预定:

  

id | company_id |点|来自|到|价格| booking_data | booker_choises | due_order_id_datetime(如果不是订单的一部分,则删除预订时)|创建|更新|删除

booking_resources:

  

id | booking_id | resource_id |来自|到|点|创建|更新|删除

资源:

  

id | company_id |名字| min_booking | max_bookings | min_points | max_points |创建|更新|删除

为了能够重现这个问题,我在两个不同的窗口中同时点击了同一个按钮。这是通过使用settimeout计时器和单击事件(使用jquery)来完成的。

<script>
function syncClick(selector,time_to_activate){
    date = new Date();
    if(date.getTime() >= time_to_activate){
        console.log('clicked');
        jQuery(selector).click();
    } else {
        setTimeout(function(){
            console.log("diff:"+(date.getTime() - time_to_activate));
            syncClick(selector,time_to_activate);
        },1);
    }
}
</script>

感谢。 / W

1 个答案:

答案 0 :(得分:-2)

以下案例:

UserA和UserB在星期一检查BookA的可用性。所以它们都会在检查后显示“可用”。使用检查可用性的存储过程“sp_CheckAvail”。它应该在两种情况下都返回true。

现在,UserA请求在星期一预订,所以点击“预订”。这本书将保留给星期一。

请求应如下所示:

call sp_CheckAvail(bookid, $date, available); //This function will check 
                                              //wheter the book is available at the moment
                                              of the request

if available
    BEGIN
      insert into reservations(bookid, date)
      values($book, $date);  //This will write the reservation only if the book is available
    END

select available as result;

对于cource,这必须全部在一个事务中运行,所以即使在同一时刻点击链接,也只有一个客户端会得到预订。

请理解我无法为您撰写完整的查询。但这样就行了。