【发布时间】:2012-07-01 23:18:47
【问题描述】:
我有一个网站,用户可以在其中购买门票,但门票数量通常是有限的,而且很快就能买到。我正在尝试实现一个托管系统,以便用户可以单击他们想要 x 数量的票,此时我会将它们置于托管状态。这样他们就可以在几分钟内输入信用卡信息并完成购买。
我有三个相关的表格:事件、门票和托管。事件表中的一行描述了事件本身,包括可用门票的最大数量。
门票表包含以下内容:
user_id:购买门票的用户
number_of_tickets:他们购买了多少张门票
event_id:相关事件
托管表包含以下内容:
user_id:正在购票的用户
number_of_tickets:他们想要多少张门票
event_id:相关事件
目前,我执行三个 MySQL 查询,一个查询最大票数,一个查询已售票数,一个查询已托管票数。然后我计算:
$remaining_tickets = $max_tickets - $tickets_sold - $tickets_in_escrow;
if ($remaining_tickets >= $tickets_desired)
{
beginEscrow($user_id, $event_id, $tickets_desired);
}
else
{
echo "Error: not enough ticket remain.";
}
我的问题是多个用户可能同时执行此代码。如果一个用户在 另一个用户已经阅读了已在托管中的门票数量之后打电话给beginEscrow,那么我可能会超卖该节目。
我正在为我的表使用 InnoDB 引擎,并且我已经阅读了如何使用 SELECT .... FOR UPDATE 锁定单行,但我没有更新单行。 beginEscrow 函数只会在托管表中插入一个新行。我通过读取具有正确事件 ID 的所有行并将每行中的票数相加来计算 $tickets_in_escrow。
也许我做错了?
我需要锁定整个表吗?
我不能成为第一个编写票务托管系统的人。我已经用谷歌搜索了自己,试图找到一些关于这种事情的教程,但被淘汰了。任何想法都会有所帮助。
谢谢!
【问题讨论】:
标签: mysql locking innodb atomic escrow