【发布时间】:2010-06-14 13:25:58
【问题描述】:
我目前正在为我的客户构建一个 PHP 电子商务网站。它进展顺利,但我遇到了障碍,想知道是否有任何 MySQL/PHP 专家可以帮助我。基本上,电子商务网站只销售一次产品(意味着每件商品只有一个数量的库存),这意味着一旦客户签出该商品,就无法再购买。
所以在结帐时,我必须检查产品是否仍有库存。假设这将是一个流量很大的网站,可能会有两个或多个客户同时尝试结帐的情况,因此他们都可以购买产品。所以为了防止这种情况,我的计划如下:
- 在产品上选择...FOR UPDATE,以锁定表行。
- 进行电子商务交易(Paypal、authorize.net 等)
- 如果电子商务交易成功,则调用 MySQL 存储过程(也有 SQL 交易)来存储订单信息等。如果失败则回滚
这个计划有可能实现吗?要执行 SELECT...FOR UPDATE,我必须启动一个 SQL 事务,但随后我还要在 MySQL 存储过程的第 3 步中启动另一个事务。我不确定会发生什么。另外,这个计划会导致僵局吗?
很抱歉这个问题太长了,但感谢您的帮助!
【问题讨论】:
-
而不是
select for update,我认为一个可用的列,作为tinyint(1),标记该项目可能是更好的选择。如果您使用select for update,则不太可能发生死锁,但点击购买按钮的客户#2 可能会等待很长时间(而客户#1 持有锁),只是为了被告知“对不起,我们缺货了。” -
我考虑了可用列,但假设两个客户同时点击“购买”,该列不会返回“可用”,因为在更新为“不可用”之前已读取两个请求?
-
对不起,如果我不清楚,我应该说使用
select for update来更新可用列。这样,您只会在检查可用性时锁定,而不是锁定整个过程。另一种选择是,在第一次检查可用列之后,在进行更新时,执行update tbl set available = 0 where id = 1 and available = 1之类的操作。如果两个人同时运行查询,则只有 1 人应该成功。然后,您可以检查更新影响了多少行。如果有 0 行受到影响,您就会遇到问题。 -
嘿 Nate,您能否通过使用 select for update 更新可用列来澄清您的意思?如果我先这样做,由于我必须进行两次交易,那会不会首先给我带来同样的问题?如果我选择第二个选项,如果付款失败,我将不得不进行另一次更新以将可用设置回 1...看起来效率不高 =/
标签: php mysql e-commerce database-deadlocks table-locking