mySQL - 防止双重预订

时间:2009-11-12 16:35:59

标签: mysql database transactions insert

我正在尝试找出在我的申请中停止双重“预订”的最佳方式。

我有一张唯一身份证表,每张只能出售一次。

我目前的想法是使用交易来检查所选产品是否可用,如果它们然后插入“状态”列,它是“保留”,同时插入“更新时间”然后用户继续支付我将状态更新为'sold'。

我每10分钟就有一个cron作业检查'status'='reserved',它已经超过10分钟前更新并删除了这些行。

有更好的方法吗?我从来没有使用过交易(我刚刚听过这个词被绑定),所以如果有人能解释我将如何做到这将是王牌。

3 个答案:

答案 0 :(得分:4)

尽管其他人提出了建议,但交易不是完整的解决方案。

听起来你在这里有一个网络应用程序,选择和购买预订需要几页(步骤)。这意味着您必须在几页内保持交易,这是不可能的。

您的方法(状态列)是正确的,但是,我会以不同的方式实现它。而不是状态列,请添加两列:reserved_byreserved_ts

  • 在预订产品时,请将reserved_by设置为用户或会话的主键,并将reserved_ts设置为now()
  • 在寻找未预留的产品时,请查找reserved_ts为空或超过10分钟的产品。 (我实际上会比你告诉你的用户要多几分钟,以避免可能的竞争条件。)
  • 清除旧保留的cron工作变得没必要了。

答案 1 :(得分:3)

您尝试对“保留”状态执行的操作主要是模拟事务行为。你让专家(mysql)为你处理它会好得多。

database transactions然后how to use them in MySQL进行一般性阅读。它们并不太复杂。请稍后在这里发布有关它们的问题,我会尽力回复。

编辑:现在我考虑了您的要求......或许使用数据库事务不是最佳解决方案 - 打开大量事务并等待用户提交交易的行动可能不是一个好的设计选择。相反,继续使用“status”=“reserved”设计,但使用数据库中的事务来设置“status”的值,以确保两个用户不同时“保留”该行

答案 2 :(得分:0)

您无需添加任何状态即可。

为了避免dirty reads,您应该将数据库设置为isolation level,以避免它们。即,REPEATABLE READ或SERIALIZABLE。

您可以全局set the isolation level或特定会话。如果您的所有会话都需要隔离,您也可以全局设置。

设置隔离级别后,您只需使用在SELECT之前启动的a transaction,如果SELECT显示它尚未保留,则可以选择更新状态。