【问题标题】:Secure MYSQL Insert multiple row if condition is true如果条件为真,则安全 MYSQL 插入多行
【发布时间】:2018-07-11 02:52:17
【问题描述】:

我正在做一个小项目,我的门票有限,用户可以购买多种数量和不同类型的门票。我需要确保只有当要购买的门票不超过每种类型的可用门票时才会插入交易。

这样做是否足够安全?

$selectAvailableTickets = getTicketAvailability(1,2,3) //Assume that this returns rows of event_id, tickets_available

foreach($selectAvailableTickets as $availableEventTicket){
    foreach($ticketsToPurchase as $purchase){
        if($purchase->event_id == $availableEventTicket->event_id){
            if($purchase->ticket_count > $availableEventTicket){
               $hasExceedingPurchase = true;
            }
        }
    }
}

if($hasExceedingPurchase) //Cancel transaction, otherwise, insert and proceed

这样的事情是否足以确保只有在购买不超过该特定类型门票的可用门票时才会进行交易?

我在想,如果有多个用户几乎同时进行交易,如果另一个人买了票并且没有给另一个人还进行了一笔交易,只是碰巧进行了一次比另一笔交易更快的交易。

【问题讨论】:

标签: php mysql database laravel transactions


【解决方案1】:

为了保护您的数据库免受所选和插入的信息不匹配的这些不必要的故障,您可以请求事务锁定。这是一个非常有趣的话题,值得更多阅读!对于您的实现,您需要知道的是,您可以请求锁,并且只有在所有查询都成功时才执行查询。

DB::transaction(function() {
    //get available ticket count
    $event = Event::where('event_id', $event_id)->lockForUpdate()->get();
    $available_tickets = $event->available;

    if($available_tickets < $tickets_to_purchase){
        //tickets where already sold, throw exception to rollback transaction
        throw new Exception();
        return
    }

    //safely create tickets since we are the only one with the lock
    $ticket = new Ticket()
    $ticket->amount_of_tickets = $tickets_to_purchase;
    $ticket->save();

    $event->available = $available_tickets - $tickets_to_purchase;
    $event->save;
});

这里我们使用pessimistic lock,这个锁意味着除了获得锁的人/php实例之外,没有人可以读取此事件的可用票数,直到锁被释放。由于我们在同一笔交易中创建门票并更新可用门票,因此我们可以确定我们是唯一能够购买上述门票的人。

当然,函数内的所有代码都可以扩展以获取所有相关信息(使用适当的锁)。在这里,您还可以使用 for 循环来获取所有票证类型的相关信息。

【讨论】:

  • 非常感谢这位好先生。现在我有最后一个问题。锁定是否会带来任何风险......网络超时?我的意思是如果有人有锁进程可能会因为进程排队而变慢,如果队列中有这么多怎么办?无论如何,如果他们的请求等待的时间过长,这比在用户数量少的情况下不太可能发生的超时要好。
  • 是的,这确实会减慢您对其他用户的应用程序的速度,但正如您已经说过的那样,这是必要的。这就是为什么你应该只在真正需要的时候使用事务,并且在你的事务中执行尽可能少的代码。
  • 我宁愿让它安全,我会一直保持这种状态,直到我找到一个性能损失更少的更好的解决方案,但这可能不会在不久的将来发生,因为我还有很多学习。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-14
  • 1970-01-01
  • 2013-05-04
相关资源
最近更新 更多