gpt4 book ai didi

mysql - 在 MySQL 上具有行锁定和事务的 Rails 应用程序提供错误数据

转载 作者:行者123 更新时间:2023-11-29 03:46:04 24 4
gpt4 key购买 nike

我正在生产中运行一个拍卖网站。我有一个拍卖模型和一个投标模型。拍卖行包含结束时间、当前价格、出价次数、最后出价人的用户名等。出价行包含用户名、拍卖ID、时间戳、价格等。

在拍卖页面上,我想显示拍卖的统计数据和最后十名竞标者,以及当时的拍卖价格。因此,通过保存出价,我在出价表中添加了一行,更新了用户的帐户,并更新了拍卖行,所有这些都在一次事务中完成。

这是我简化的出价模型:

class Bid < ActiveRecord::Base
belongs_to :auction, :inverse_of => :bids
belongs_to :account, :inverse_of => :bids
scope :recent, order('id DESC').limit(10) # used to get last ten bids
before_create :update_auction
after_create :update_account

def update_auction
auction.lock!
auction.highest_bidder = username
auction.price = ...
# more stuff
auction.save!
end

def update_account
# do stuff
account.save!
end

但是,当有足够多的人同时点击出价按钮时,拍卖统计数据就会变得不一致。计数器减一或二,或者最高出价者与出价表中的最后一行不匹配。我想,由于这三个写入被包装在一个事务中,并且我锁定了一个共享行(拍卖),数据会很好,但事实并非如此。

我可以重写应用程序以动态查询出价表以查找每个获胜者、出价计数等,但这会使我进行的许多其他查询变得复杂。

那么这里合适的并发控制是什么呢?我需要在拍卖行中保存获胜者,但我需要该获胜者成为出价表中的最后一行。而且我同时对同一行进行了大量写入。

最佳答案

我没有看到您打开交易,这是您应该尝试的一种方式:

def update_auction
Auction.transaction do
auction.lock!
auction.highest_bidder = username
auction.price = ...
# more stuff
auction.save!
end
end

另请查看 ActiveRecord::Locking::Pessimistic

另一种方法是当有人出价时您不更新拍卖,因为出价对拍卖记录本身没有影响。

这是我的做法:

  • 假设每个 Action 在拍卖表中都有一个“截止日期”列。

  • 用户 XY 尝试在您的出价验证过程中出价:

    • 检查拍卖是否仍在进行中,如果没有则放置验证错误,告知现在出价为时已晚
    • 检查是否已经有更高的拍卖出价,如果是,则放置一个验证错误,告知他的出价太低

因此,这可以确保不会出现无效的出价。拍卖结束后无法出价。

要确定获胜者,您只需执行以下操作

winning_bid = the_auction.bids.maximum(:amount)
winner = winning_bid.account

关于mysql - 在 MySQL 上具有行锁定和事务的 Rails 应用程序提供错误数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5208764/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com