拍卖出价-将选择锁定在共享模式保持信息的最新


Auction Bid - Will SELECT LOCK IN SHARE MODE keep information at its most recent?

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

我已经归结为使用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,它会更合适,那将是非常有帮助的!!!

编辑:这本质上是一个并发问题,我不想用不正确/旧的数据检查当前出价,这会导致某些出价的"丢失更新"。

两次同时更新本身不会导致死锁,只是暂时的阻塞。让我们称之为投标A和投标B

尽管我们认为它们是同时发生的,但首先会获得一个锁。我们说A到达那里的速度快1ms。

CCD_ 7获取对所述行的锁定。B的锁请求进入队列,必须等待属于A的锁被释放。一旦锁定A被释放,B就获取其锁定。

您的代码可能还有更多内容,但从您的问题来看,正如我所描述的,不存在死锁情况。为了死锁,A必须等待B释放它对另一个资源的锁定,但B在获得对A的资源的锁定之前不会释放它的锁定。

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

A。使用适当的事务隔离级别(可能是可重复读取,这是InnoDB中的默认级别),并在显式事务中执行选择和更新。

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

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

UPDATE ...
WHERE currentBid < newBid

就我个人而言,我会选择A,因为我不知道你的逻辑有多复杂。

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

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

关于并发性,关键是使事务尽可能短。进去,出去。默认情况下,您无法读取正在更新的记录,因为它处于不确定状态。这些更新和读取应该只需要几分之一秒。