2010-04-16 3 views
0

일부 조건이 충족 될 때 before_save에 일부 논리가 있습니다. 새 행을 데이터베이스 + 1의 최대 special_number와 동일한 special_number으로 만듭니다. 조건이 충족되지 않으면 다른 작업을 수행하므로 자동 증분을 사용할 수 없습니다.ActiveRecord와 transactions before_and_save와 save 사이

걱정할 점은 두 번째 스레드가 실행될 때이 데이터베이스에서 동시에 작동하는 두 스레드가 동일한 special_number을 선택할 수 있습니다. 첫 번째는 저축입니다. before_save 사이에서 데이터베이스를 잠그고 저장을 마무리하는 방법이 있습니까? 나는 모든 저축이 거래에서 보내진다는 것을 알고있다. 이것이 나에게 도움이 될 것인가?

SELECT special_num FROM nums FOR UPDATE; 
UPDATE nums SET special_num = special_num + 1; 

당신에 대해 읽을 수 있습니다 :

def before_save 
    if things_are_just_right 
    # -- Issue some kind of lock? 
    # -- self.lock? I have no idea 
    # Pick new special_number 
    new_special = self.class.maximum('special_number') + 1 
    write_attribute('special_number',new_special) 
    else 
    # No need to lock in this case 
    write_attribute('special_number',some_other_number) 
    end 
end 

답변

1

이 업데이트를 선택 사용할 수있는 특별한 수는 항상 1로 증가하고있다, 당신은 "격차"가 기운, 그리고는 DB-으로 저장된 여기에 : select for update

DB를 잠그고 있으므로 특별한 번호의 업데이트가 많은 경우 성능 문제가 발생할 수 있습니다.

당신은 (경우에 트랜잭션이 실패) 매우, 매우 빠른 미리 형성되므로 :) 난

+0

을하는 쉬운 방법은, "INC"기능을 memcahced 사용하는 것입니다 특별한 NUM의 마음을 가진 간격을 해달라고하는 경우 실제로 MySQL을 사용하지 않습니다! (heroku + sqlite3) - sqlite는 동등한 기능을 가지고 있다고 생각하지 않습니까? –