2011-03-06 3 views
2

프로덕션 환경에서 경매 사이트를 운영하고 있습니다. 나는 Auction 모델과 Bid 모델을 가지고 있습니다. 입찰 행에는 사용자 이름, 경매 ID, 타임 스탬프, 가격 등이 포함되어 있습니다.잘못된 데이터를 제공하는 MySQL의 행 잠금 및 트랜잭션이있는 레일 앱

옥션 페이지에서 경매 행을 선택하고 싶습니다. 그 당시의 경매 가격과 함께 경매의 통계와 지난 10 명의 입찰자를 표시했습니다. 따라서 입찰가를 저장하면 입찰 테이블에 행을 추가하고 사용자 계정을 업데이트하며 경매 행을 한 번에 업데이트 할 수 있습니다.

이 내 단순화 입찰 모델 : 충분한 사람들이 한 번에 입찰 버튼을 클릭하면

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 

그러나, 경매 통계가 일치하지 않을. 카운터가 1 ~ 2 개 꺼져 있거나 최고 입찰자가 입찰가 표의 마지막 행과 일치하지 않습니다. 나는이 세 글이 트랜잭션으로 래핑 되었기 때문에 하나의 공유 행 (경매)을 잠그기 때문에 데이터는 괜찮을 것이라고 생각했지만 그렇지 않다.

나는 각 우승자, 입찰 횟수 등을 찾기 위해 동적으로 입찰가 테이블을 쿼리하도록 앱을 다시 작성할 수 있지만 그 작업은 다른 많은 쿼리를 복잡하게 만듭니다.

여기에 적절한 동시성 제어 란 무엇입니까? 경매 행에 승자를 저장해야하지만 승자가 입찰가 테이블의 마지막 행이되어야합니다. 그리고 나는 한 번에 같은 줄에 많은 글을 쓰고 있습니다. 난 당신이 트랜잭션을 열어야 표시되지 않습니다

답변

0

는, 여기 당신이 시도해야 방법 :

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

는 또한 ActiveRecord::Locking::Pessimistic

또 다른 방법을 살펴 가지고하면 경매를 갱신하지 않는다는 것입니다 입찰이 경매 레코드 자체에 영향을주지 않기 때문에 누군가가 입찰을 할 때. 여기

내가 그것을 할 것입니다 방법은 다음과 같습니다

  • 이 모든 행동이 경매 테이블에서 "유효 기간"열이 있다고 가정합니다.

  • 사용자 XY 입찰의 검증 과정에서 입찰을 배치하려고 당신이 할 :

    • 확인 유효성 검사 오류가 입찰을 배치 너무 늦기 것을 말해 두지 경우 경매가 열려있는 경우
    • 네 자신의 입찰

그래서이 더 보장하지 너무 낮다는 것을 알려주는 유효성 검사 오류를 배치하면 더 높은 경매에 입찰이 이미있을 경우

  • 확인 잘못된 입찰가를 설정할 수 있습니다. 경매가 끝나면 입찰가를 설정할 수 없습니다.

    당신은 당신이 제공 한 기준에 따라,

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

    바이올렛이 제안한'auction.lock!'방법은 완벽하게 합법적 인 것처럼 뭔가를 할 승자를 결정합니다. 그 방법에 문제가 있습니까? –

    +0

    아니, 그 이유는 내 대답을 편집했습니다 :) – sled

    +0

    답장을 보내 주셔서 감사합니다.before_create 및 after_create 콜백은 http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html에 설명 된대로 암시 적으로 트랜잭션을 만듭니다. 나는 또한 3 개의 모든 쓰기가 트랜잭션 내부에 있다는 SQL 결과로 알 수있다. 그리고 당신은 경매로 볼 수 있습니다. 잠금! 이미 비관적 인 잠금을하고 있습니다. 마지막으로, 나는 또한 내 게시물에서 동적으로 우승자를 계산하는 방법을 알고 있습니다. 나는 경매 및 최고 우승자 목록을 효율적으로 표시하고 사용자가 얻은 모든 경매를 보여주는 것을 복잡하게하기 때문에이를 원하지 않습니다. – icecream