【问题标题】:How to insert only if entries of the same date is not more than 4?仅当相同日期的条目不超过4个时如何插入?
【发布时间】:2019-12-23 17:28:15
【问题描述】:

我正在创建一个模块,其中customers(所有客户,而不是个人)应该只能在 2 个表中预订同一日期的时间表,最多 5 次,即acceptance_bookingsturnover_bookings .

例如,5 位客户预订了同一日期 (07-17-2019),其中 3 位是 acceptance_booking,2 位是 turnover_booking。如果其他客户试图在同一日期预订,他们应该被拒绝。

目前我的实现如下所示:

** START OF TRANSACTION **

** CODE FOR INSERTING ACCEPTANCE OR TURNOVER BOOKING ** 

$acceptance_bookings = AcceptanceBooking::selectRaw("DATE(date) as date")
            ->havingRaw("DATE(date) = '$dateString'")
            ->get()
            ->count();

$turnover_bookings = TurnoverBooking::selectRaw("DATE(date) as date")
            ->havingRaw("DATE(date) = '$dateString'")
            ->get()
            ->count();

$total_count = $acceptance_bookings + $turnover_bookings;

if($total_count > 5) 
    ** ROLLBACK THE DB TRANSACTION

** END OF TRANSACTION

我担心在竞争条件下,两个插入都有可能通过代码末尾的验证检查,该检查检查该日期是否有超过 5 个条目。

在我的实现(上面的代码)中,我在检查它是否实际上已经超过限制之前插入预订,如果超过 5 个条目则回滚交易。将条件放在插入之前可能会在竞争条件中产生相同的结果。

处理这种情况以避免竞争条件的最佳方法是什么?我要保持的严格要求是,两张桌子上的相同预订时间表的条目不得超过 5 个。

注意:我无法更改表格,例如尝试创建预订表格并使用参考 ID 来确定它是接受预订还是营业额预订,因为我正在集成一个已经工作的系统。

【问题讨论】:

标签: php mysql laravel validation query-optimization


【解决方案1】:

你的代码有正确的想法;问题是什么? BEGIN 开头,COMMIT 结尾(如果没有失败)。

还有一点:SELECT 必须是 SELECT .. FOR UPDATE。这“锁定”了您正在计数的行 --> 避免了竞争问题。

【讨论】:

  • 我的代码在一个事务中,所以应该没问题。我真的需要锁定选定的行吗?因为这些值几乎永远不会更新。我担心的是比赛条件。如果某个日期只剩下一个空位,并且多个用户同时预订,我认为他们有可能通过这些验证。
  • @Rick - 请参阅 stackoverflow.com/a/48629009/1766831 以了解对 FOR UPDATE 的精彩讨论。
猜你喜欢
  • 1970-01-01
  • 2017-09-19
  • 1970-01-01
  • 1970-01-01
  • 2021-01-18
  • 1970-01-01
  • 1970-01-01
  • 2015-01-21
  • 1970-01-01
相关资源
最近更新 更多