拍卖出价 - 选择锁定共享模式会保留最新信息吗?

时间:2012-01-26 16:31:42

标签: php mysql sql locking innodb

我目前正在研究如何在拍卖网站项目中管理大量出价。由于很可能有些人可能会在同一时间发出出价,因此很明显我需要确保有锁以防止任何数据损坏。

我已经开始使用SELECT LOCK IN SHARE MODE来表明If any of these rows were changed by another transaction that has not yet committed, your query waits until that transaction ends and then uses the latest values.

http://dev.mysql.com/doc/refman/5.1/en/innodb-locking-reads.html

这向我建议,出价将进入一个队列,每个出价都会被处理并检查以确保出价高于当前出价,并且如果自插入这个队列以来有更改,那么最新出价使用金额。

但是,我已经读过可能存在破坏性的死锁问题,其中两个用户同时尝试出价并且没有查询可以保持锁定。因此我也考虑使用SELECT FOR UPDATE,但这也将禁用任何我不太确定的读取。

如果有人能够对这个问题有所了解,那么如果你能推荐任何其他数据库,比如NoSQL更适合那么这将是非常有用的!

编辑:这本质上是一个并发问题,我不想用不正确/旧数据检查当前出价,因此会对某些出价产生“丢失更新”。

1 个答案:

答案 0 :(得分:3)

本身,两个同步更新不会导致死锁,只是瞬态阻塞。我们称之为出价A和出价B

虽然我们正在同时考虑它们,但人们会首先获得锁定。我们会说A可以快1毫秒到达那里。

A获取有关行的锁定。 B让锁定请求进入队列,必须等待释放属于A的锁。锁定A一旦释放,B就会锁定它。

您的代码可能还有更多内容,但是根据您的问题,正如我所描述的那样,没有死锁方案。为了解除僵局,A必须等待B释放它对另一个资源的锁定,但BA获取锁定之前不会释放锁定资源。

如果您需要实时验证出价,可以:

一个。使用适当的事务隔离级别(可能是可重复读取,这是InnoDB中的默认值),并在显式事务中执行select和update。

BEGIN TRAN
    SELECT ... FOR UPDATE
    IF ...
    UPDATE ...
COMMIT

B中。在Update语句中执行检查逻辑。换句话说,构建您的UPDATE查询,使其仅在当前出价低于新出价时影响行。如果没有记录受到影响,则出价过低。这是一种可行的方法,可以减少数据库的工作,但有自己的考虑。

UPDATE ...
WHERE currentBid < newBid

我个人的投票是选择A,因为我不知道你的逻辑是多么复杂。

repeatable read隔离级别将确保每次在事务中读取给定记录时,该值都保证相同。它通过在行上保持锁定来阻止其他人更新给定行,直到您的事务提交或回滚为止。一个连接无法更新您的表,直到最后一个完成它的事务。

底线是您的选择/更新将在您的数据库中是原子的,因此您不必担心丢失更新。

关于并发性,关键在于保持您的交易尽可能短。进去,滚出去。默认情况下,您无法读取正在更新的记录,因为它处于不确定状态。这些更新和读取应该只需要一小部分时间。